rust/hg-core/src/repo.rs
author Rapha?l Gom?s <rgomes@octobus.net>
Mon, 04 Nov 2024 11:00:58 +0100
changeset 52298 db065b33fa56
parent 52290 a3fa37bdb7ec
child 52301 79e8118cd846
permissions -rw-r--r--
rust-dirstate: merge `dirstate_tree` module into `dirstate` The historical reasonning for `dirstate_tree` existing in the first place is that a new approach was needed for the tree-like dirstate and it was easier to start somewhat fresh. Now that the former dirstate is (long) gone, we can merge those two modules to avoid the confusion that even the module creators sometimes get.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
     1
use crate::config::{Config, ConfigError, ConfigParseError};
52298
db065b33fa56 rust-dirstate: merge `dirstate_tree` module into `dirstate`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52290
diff changeset
     2
use crate::dirstate::dirstate_map::{DirstateIdentity, DirstateMapWriteMode};
db065b33fa56 rust-dirstate: merge `dirstate_tree` module into `dirstate`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52290
diff changeset
     3
use crate::dirstate::on_disk::Docket as DirstateDocket;
db065b33fa56 rust-dirstate: merge `dirstate_tree` module into `dirstate`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52290
diff changeset
     4
use crate::dirstate::owning::OwningDirstateMap;
47956
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
     5
use crate::dirstate::DirstateParents;
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::errors::HgResultExt;
48421
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
     7
use crate::errors::{HgError, IoResultExt};
48417
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48409
diff changeset
     8
use crate::lock::{try_with_lock_no_wait, LockError};
52156
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
     9
use crate::requirements::DIRSTATE_TRACKED_HINT_V1;
52178
bd8081e9fd62 rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52167
diff changeset
    10
use crate::revlog::changelog::Changelog;
47961
4d2a5ca060e3 rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents: 47960
diff changeset
    11
use crate::revlog::filelog::Filelog;
52178
bd8081e9fd62 rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52167
diff changeset
    12
use crate::revlog::manifest::{Manifest, Manifestlog};
bd8081e9fd62 rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52167
diff changeset
    13
use crate::revlog::options::default_revlog_options;
bd8081e9fd62 rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52167
diff changeset
    14
use crate::revlog::{RevlogError, RevlogType};
50228
fc8e37c380d3 dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50227
diff changeset
    15
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
    16
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
    17
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
    18
use crate::utils::SliceExt;
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
    19
use crate::vfs::{is_dir, is_file, Vfs, VfsImpl};
52156
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
    20
use crate::DirstateError;
52178
bd8081e9fd62 rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52167
diff changeset
    21
use crate::{exit_codes, requirements, NodePrefix, UncheckedRevision};
48419
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
    22
use std::cell::{Ref, RefCell, RefMut};
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
    23
use std::collections::HashSet;
48421
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
    24
use std::io::Seek;
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
    25
use std::io::SeekFrom;
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
    26
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
    27
use std::path::{Path, PathBuf};
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    28
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
    29
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
    30
52050
ea0467ed76aa rust-dirstate-map: use a more precise identity
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52045
diff changeset
    31
/// Docket file identity, data file uuid and the data size
ea0467ed76aa rust-dirstate-map: use a more precise identity
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52045
diff changeset
    32
type DirstateV2Identity = (Option<DirstateIdentity>, Option<Vec<u8>>, usize);
50252
a6b8b1ab9116 branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49937 50245
diff changeset
    33
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    34
/// A repository on disk
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    35
pub struct Repo {
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    36
    working_directory: PathBuf,
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    37
    dot_hg: PathBuf,
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    38
    store: PathBuf,
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
    39
    requirements: HashSet<String>,
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    40
    config: Config,
49177
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49164
diff changeset
    41
    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
    42
    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
    43
    changelog: LazyCell<Changelog>,
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49164
diff changeset
    44
    manifestlog: LazyCell<Manifestlog>,
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    45
}
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    46
46446
1dcd9c9975ed rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    47
#[derive(Debug, derive_more::From)]
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    48
pub enum RepoError {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    49
    NotFound {
46503
d8730ff51d5a rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    50
        at: PathBuf,
46446
1dcd9c9975ed rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    51
    },
1dcd9c9975ed rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    52
    #[from]
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    53
    ConfigParseError(ConfigParseError),
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    54
    #[from]
46446
1dcd9c9975ed rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    55
    Other(HgError),
1dcd9c9975ed rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    56
}
1dcd9c9975ed rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
    57
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    58
impl From<ConfigError> for RepoError {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    59
    fn from(error: ConfigError) -> Self {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    60
        match error {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    61
            ConfigError::Parse(error) => error.into(),
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    62
            ConfigError::Other(error) => error.into(),
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    63
        }
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    64
    }
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    65
}
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
    66
52042
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
diff changeset
    67
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: 52032
diff changeset
    68
    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: 52032
diff changeset
    69
        match value {
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
diff changeset
    70
            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: 52032
diff changeset
    71
                format!(
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
diff changeset
    72
                    "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: 52032
diff changeset
    73
                    at.display()
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
diff changeset
    74
                ),
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
diff changeset
    75
                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: 52032
diff changeset
    76
                None,
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
diff changeset
    77
            ),
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
diff changeset
    78
            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: 52032
diff changeset
    79
                HgError::Abort {
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
diff changeset
    80
                    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: 52032
diff changeset
    81
                        &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: 52032
diff changeset
    82
                    )
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
diff changeset
    83
                    .to_string(),
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
diff changeset
    84
                    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: 52032
diff changeset
    85
                    hint: None,
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
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: 52032
diff changeset
    87
            }
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
diff changeset
    88
            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: 52032
diff changeset
    89
        }
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52032
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: 52032
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: 52032
diff changeset
    92
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    93
impl Repo {
47405
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47404
diff changeset
    94
    /// 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
    95
    /// its ancestors
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47404
diff changeset
    96
    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
    97
        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
    98
        // 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
    99
        // as-is.
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47404
diff changeset
   100
        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
   101
            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
   102
                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
   103
            }
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47404
diff changeset
   104
        }
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49217
diff changeset
   105
        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
   106
            at: current_directory,
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49217
diff changeset
   107
        })
47405
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47404
diff changeset
   108
    }
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47404
diff changeset
   109
46505
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46503
diff changeset
   110
    /// 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
   111
    /// 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
   112
    /// ancestors.
46503
d8730ff51d5a rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
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
    /// 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
   115
    /// 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
   116
    /// 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
   117
    /// 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
   118
    pub fn find(
d8730ff51d5a rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
   119
        config: &Config,
47404
ebdef6283798 rhg: read [paths] for `--repository` value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47374
diff changeset
   120
        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
   121
    ) -> Result<Self, RepoError> {
d8730ff51d5a rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
   122
        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
   123
            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
   124
                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
   125
            } 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
   126
                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
   127
            } else {
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49217
diff changeset
   128
                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
   129
            }
46503
d8730ff51d5a rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
   130
        } else {
47405
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47404
diff changeset
   131
            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
   132
            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
   133
        }
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   134
    }
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   135
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   136
    /// 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
   137
    fn new_at_path(
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
   138
        working_directory: PathBuf,
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46484
diff changeset
   139
        config: &Config,
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
   140
    ) -> Result<Self, RepoError> {
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   141
        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
   142
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49217
diff changeset
   143
        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
   144
            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
   145
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
   146
        let hg_vfs = VfsImpl::new(dot_hg.to_owned(), false);
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51863
diff changeset
   147
        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
   148
        let relative =
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   149
            reqs.contains(requirements::RELATIVE_SHARED_REQUIREMENT);
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   150
        let shared =
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   151
            reqs.contains(requirements::SHARED_REQUIREMENT) || relative;
46463
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
   152
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
   153
        // From `mercurial/localrepo.py`:
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
   154
        //
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
   155
        // 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
   156
        // 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
   157
        // 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
   158
        // 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
   159
        // is not present, refer checkrequirementscompat() for that
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
        // 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
   162
        // 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
   163
        // .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
   164
        // current repository needs to be reshared
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
   165
        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
   166
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   167
        let store_path;
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   168
        if !shared {
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   169
            store_path = dot_hg.join("store");
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   170
        } else {
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   171
            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
   172
            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
   173
                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
   174
                    .to_owned();
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   175
            if relative {
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   176
                shared_path = dot_hg.join(shared_path)
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   177
            }
47780
cf5f8da2244c rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents: 47674
diff changeset
   178
            if !is_dir(&shared_path)? {
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   179
                return Err(HgError::corrupted(format!(
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   180
                    ".hg/sharedpath points to nonexistent directory {}",
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   181
                    shared_path.display()
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
   182
                ))
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
   183
                .into());
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   184
            }
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   185
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   186
            store_path = shared_path.join("store");
46463
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
   187
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
   188
            let source_is_share_safe = requirements::load(VfsImpl::new(
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
   189
                shared_path.to_owned(),
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
   190
                true,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
   191
            ))?
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51863
diff changeset
   192
            .contains(requirements::SHARESAFE_REQUIREMENT);
46463
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46462
diff changeset
   193
48809
1d5fd9def5ac rhg: simplify the handling of share-safe config mismatch
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48510
diff changeset
   194
            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
   195
                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
   196
            }
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
   197
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
   198
            if share_safe {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
   199
                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
   200
            }
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   201
        }
46613
f64b6953db70 rhg: Bug fix: with share-safe, always read store requirements
Simon Sapin <simon.sapin@octobus.net>
parents: 46601
diff changeset
   202
        if share_safe {
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
   203
            reqs.extend(requirements::load(VfsImpl::new(
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
   204
                store_path.to_owned(),
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
   205
                true,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
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
        }
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   208
46741
25e3dac511f0 rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
   209
        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
   210
            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
   211
        } else {
25e3dac511f0 rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
   212
            config.clone()
25e3dac511f0 rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents: 46740
diff changeset
   213
        };
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
   214
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   215
        let repo = Self {
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   216
            requirements: reqs,
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   217
            working_directory,
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   218
            store: store_path,
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   219
            dot_hg,
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
   220
            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
   221
            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
   222
            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
   223
            changelog: LazyCell::new(),
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49164
diff changeset
   224
            manifestlog: LazyCell::new(),
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   225
        };
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   226
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   227
        requirements::check(&repo)?;
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   228
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   229
        Ok(repo)
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   230
    }
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   231
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   232
    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
   233
        &self.working_directory
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   234
    }
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   235
46462
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   236
    pub fn requirements(&self) -> &HashSet<String> {
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   237
        &self.requirements
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   238
    }
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
   239
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
   240
    pub fn config(&self) -> &Config {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
   241
        &self.config
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
   242
    }
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46485
diff changeset
   243
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   244
    /// 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
   245
    /// (`.hg/store`).
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51863
diff changeset
   246
    pub fn hg_vfs(&self) -> VfsImpl {
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
   247
        VfsImpl::new(self.dot_hg.to_owned(), false)
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   248
    }
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   249
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   250
    /// For accessing repository store files (in `.hg/store`)
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51863
diff changeset
   251
    pub fn store_vfs(&self) -> VfsImpl {
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
   252
        VfsImpl::new(self.store.to_owned(), false)
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   253
    }
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
    /// For accessing the working copy
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51863
diff changeset
   256
    pub fn working_directory_vfs(&self) -> VfsImpl {
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
   257
        VfsImpl::new(self.working_directory.to_owned(), false)
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   258
    }
46601
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   259
48417
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48409
diff changeset
   260
    pub fn try_with_wlock_no_wait<R>(
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48409
diff changeset
   261
        &self,
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48409
diff changeset
   262
        f: impl FnOnce() -> R,
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48409
diff changeset
   263
    ) -> Result<R, LockError> {
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51863
diff changeset
   264
        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
   265
    }
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48409
diff changeset
   266
50655
1e2c6cda2309 rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   267
    /// 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
   268
    /// 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
   269
    /// 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
   270
    /// 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
   271
    /// 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
   272
    /// v1 file.
50657
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   273
    /// 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: 50655
diff changeset
   274
    /// 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: 50655
diff changeset
   275
    /// 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: 50655
diff changeset
   276
    /// in all occasions.
50655
1e2c6cda2309 rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   277
    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
   278
        self.requirements
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 46822
diff changeset
   279
            .contains(requirements::DIRSTATE_V2_REQUIREMENT)
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 46822
diff changeset
   280
    }
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 46822
diff changeset
   281
48409
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48069
diff changeset
   282
    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
   283
        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
   284
    }
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48069
diff changeset
   285
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48069
diff changeset
   286
    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
   287
        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
   288
    }
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48069
diff changeset
   289
49091
9b5334c1e499 rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
   290
    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
   291
        self.requirements
9b5334c1e499 rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
   292
            .contains(requirements::NODEMAP_REQUIREMENT)
9b5334c1e499 rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
   293
    }
9b5334c1e499 rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
   294
47956
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   295
    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
   296
        Ok(self
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   297
            .hg_vfs()
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   298
            .read("dirstate")
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   299
            .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
   300
            .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
   301
    }
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   302
52050
ea0467ed76aa rust-dirstate-map: use a more precise identity
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52045
diff changeset
   303
    fn dirstate_identity(&self) -> Result<Option<DirstateIdentity>, HgError> {
50245
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   304
        Ok(self
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   305
            .hg_vfs()
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   306
            .symlink_metadata("dirstate")
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   307
            .io_not_found_as_none()?
52050
ea0467ed76aa rust-dirstate-map: use a more precise identity
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52045
diff changeset
   308
            .map(DirstateIdentity::from))
50245
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   309
    }
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   310
47956
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   311
    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
   312
        Ok(*self
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49164
diff changeset
   313
            .dirstate_parents
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49164
diff changeset
   314
            .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
   315
    }
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
   316
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
   317
    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
   318
        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
   319
        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
   320
            DirstateParents::NULL
50655
1e2c6cda2309 rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   321
        } else if self.use_dirstate_v2() {
52298
db065b33fa56 rust-dirstate: merge `dirstate_tree` module into `dirstate`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52290
diff changeset
   322
            let docket_res = crate::dirstate::on_disk::read_docket(&dirstate);
50657
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   323
            match docket_res {
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   324
                Ok(docket) => docket.parents(),
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   325
                Err(_) => {
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   326
                    log::info!(
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   327
                        "Parsing dirstate docket failed, \
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   328
                        falling back to dirstate-v1"
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   329
                    );
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   330
                    *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: 50655
diff changeset
   331
                        &dirstate,
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   332
                    )?
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   333
                }
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   334
            }
47374
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 46822
diff changeset
   335
        } else {
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49217
diff changeset
   336
            *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
   337
        };
48419
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
   338
        self.dirstate_parents.set(parents);
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47407
diff changeset
   339
        Ok(parents)
46601
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   340
    }
47956
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   341
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
   342
    /// 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
   343
    /// 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
   344
    /// since we last read the dirstate.
52050
ea0467ed76aa rust-dirstate-map: use a more precise identity
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52045
diff changeset
   345
    /// Namely the docket file identity, data file uuid and the data size.
50244
07d030b38097 rust-dirstate-v2: don't write dirstate if data file has changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50243
diff changeset
   346
    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
   347
        &self,
52050
ea0467ed76aa rust-dirstate-map: use a more precise identity
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52045
diff changeset
   348
    ) -> Result<DirstateV2Identity, HgError> {
48420
c7c23bb036c9 rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents: 48419
diff changeset
   349
        assert!(
50655
1e2c6cda2309 rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   350
            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
   351
            "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
   352
        );
50245
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   353
        // 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
   354
        // 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
   355
        // 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
   356
        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
   357
        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
   358
        if dirstate.is_empty() {
50245
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   359
            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
   360
        } else {
52298
db065b33fa56 rust-dirstate: merge `dirstate_tree` module into `dirstate`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52290
diff changeset
   361
            let docket_res = crate::dirstate::on_disk::read_docket(&dirstate);
50657
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   362
            match docket_res {
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   363
                Ok(docket) => {
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   364
                    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: 50655
diff changeset
   365
                    Ok((
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   366
                        identity,
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   367
                        Some(docket.uuid.to_owned()),
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   368
                        docket.data_size(),
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   369
                    ))
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   370
                }
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   371
                Err(_) => {
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   372
                    log::info!(
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   373
                        "Parsing dirstate docket failed, \
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   374
                        falling back to dirstate-v1"
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   375
                    );
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   376
                    let parents =
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   377
                        *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: 50655
diff changeset
   378
                            &dirstate,
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   379
                        )?;
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   380
                    self.dirstate_parents.set(parents);
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   381
                    Ok((identity, None, 0))
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   382
                }
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   383
            }
48420
c7c23bb036c9 rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents: 48419
diff changeset
   384
        }
c7c23bb036c9 rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents: 48419
diff changeset
   385
    }
c7c23bb036c9 rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents: 48419
diff changeset
   386
47956
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   387
    fn new_dirstate_map(&self) -> Result<OwningDirstateMap, DirstateError> {
50655
1e2c6cda2309 rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   388
        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
   389
            // 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
   390
            // 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
   391
            // (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
   392
            // 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
   393
            // 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
   394
            // 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
   395
            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
   396
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50234
diff changeset
   397
            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
   398
                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
   399
                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
   400
                    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
   401
                        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
   402
                    }
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50234
diff changeset
   403
                    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
   404
                        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
   405
                            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
   406
                        )) => {
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50234
diff changeset
   407
                            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
   408
                                "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
   409
                                context,
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50234
diff changeset
   410
                                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
   411
                                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
   412
                            );
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
                            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
   414
                        }
50657
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   415
                        _ => {
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   416
                            log::info!(
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   417
                                "Reading dirstate v2 failed, \
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   418
                                falling back to v1"
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   419
                            );
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   420
                            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: 50655
diff changeset
   421
                        }
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
   422
                    },
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
                }
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
            }
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
            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
   426
                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
   427
                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
   428
                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
   429
            );
50252
a6b8b1ab9116 branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49937 50245
diff changeset
   430
            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
   431
        } else {
50657
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   432
            self.new_dirstate_map_v1()
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   433
        }
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   434
    }
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   435
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   436
    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: 50655
diff changeset
   437
        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: 50655
diff changeset
   438
        let identity = self.dirstate_identity()?;
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   439
        let dirstate_file_contents = self.dirstate_file_contents()?;
52043
e1fe336c007a rust-repo: don't use on-disk dirstate parents in v1
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52042
diff changeset
   440
        let parents = self.dirstate_parents()?;
50657
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   441
        if dirstate_file_contents.is_empty() {
52043
e1fe336c007a rust-repo: don't use on-disk dirstate parents in v1
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52042
diff changeset
   442
            self.dirstate_parents.set(parents);
52029
88aa21d654e5 rust-dirstate: actually remember the identity
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51864
diff changeset
   443
            Ok(OwningDirstateMap::new_empty(Vec::new(), identity))
50657
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   444
        } else {
52043
e1fe336c007a rust-repo: don't use on-disk dirstate parents in v1
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52042
diff changeset
   445
            // Ignore the dirstate on-disk parents, they may have been set in
e1fe336c007a rust-repo: don't use on-disk dirstate parents in v1
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52042
diff changeset
   446
            // the repo before
e1fe336c007a rust-repo: don't use on-disk dirstate parents in v1
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52042
diff changeset
   447
            let (map, _) =
50657
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   448
                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: 50655
diff changeset
   449
            self.dirstate_parents.set(parents);
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50655
diff changeset
   450
            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
   451
        }
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50222
diff changeset
   452
    }
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50222
diff changeset
   453
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50222
diff changeset
   454
    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
   455
        &self,
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50222
diff changeset
   456
    ) -> 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
   457
        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
   458
        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
   459
        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
   460
        if dirstate_file_contents.is_empty() {
52029
88aa21d654e5 rust-dirstate: actually remember the identity
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51864
diff changeset
   461
            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
   462
        }
52298
db065b33fa56 rust-dirstate: merge `dirstate_tree` module into `dirstate`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52290
diff changeset
   463
        let docket =
db065b33fa56 rust-dirstate: merge `dirstate_tree` module into `dirstate`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52290
diff changeset
   464
            crate::dirstate::on_disk::read_docket(&dirstate_file_contents)?;
50234
2be6d5782728 dirstate: add a synchronisation point in the middle of the read
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50228
diff changeset
   465
        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
   466
            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
   467
            "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
   468
        );
50227
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50222
diff changeset
   469
        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
   470
        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
   471
        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
   472
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50234
diff changeset
   473
        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
   474
        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
   475
        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
   476
50227
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50222
diff changeset
   477
        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
   478
            // 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
   479
            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
   480
            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
   481
                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
   482
                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
   483
                    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
   484
                        // 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
   485
                        // 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
   486
                        //
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
                        // 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
   488
                        // `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
   489
                        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
   490
                            // 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
   491
                            // 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
   492
                            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
   493
                        }
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
                        _ => {
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
                            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
   496
                                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
   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
                        }
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50234
diff changeset
   499
                    }
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50234
diff changeset
   500
                }
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
                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
   502
            };
50245
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   503
            OwningDirstateMap::new_v2(
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   504
                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
   505
            )
50227
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50222
diff changeset
   506
        } 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
   507
            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
   508
                .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
   509
                .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
   510
                .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
   511
            {
50243
6cce0afc1454 rust-dirstate: remember the data file uuid dirstate was loaded with
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50239
diff changeset
   512
                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
   513
                    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
   514
                ),
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
   515
                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
   516
                    // 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
   517
                    // 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
   518
                    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
   519
                }
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
                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
   521
            }
50227
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50222
diff changeset
   522
        }?;
50222
ecd28d89c29e dirstate-v2: add devel config option to control write behavior
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50221
diff changeset
   523
50227
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50222
diff changeset
   524
        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
   525
            .config()
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50222
diff changeset
   526
            .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
   527
            .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
   528
            .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
   529
        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
   530
            "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
   531
            "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
   532
            "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
   533
            _ => DirstateMapWriteMode::Auto,
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50222
diff changeset
   534
        };
50222
ecd28d89c29e dirstate-v2: add devel config option to control write behavior
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50221
diff changeset
   535
52045
a8cf6a852f11 rust-dirstate: pass dirstate tracked key from the requirements
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52043
diff changeset
   536
        let tracked_hint =
a8cf6a852f11 rust-dirstate: pass dirstate tracked key from the requirements
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52043
diff changeset
   537
            self.requirements().contains(DIRSTATE_TRACKED_HINT_V1);
a8cf6a852f11 rust-dirstate: pass dirstate tracked key from the requirements
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52043
diff changeset
   538
a8cf6a852f11 rust-dirstate: pass dirstate tracked key from the requirements
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52043
diff changeset
   539
        map.with_dmap_mut(|m| {
a8cf6a852f11 rust-dirstate: pass dirstate tracked key from the requirements
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52043
diff changeset
   540
            m.set_write_mode(write_mode);
a8cf6a852f11 rust-dirstate: pass dirstate tracked key from the requirements
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52043
diff changeset
   541
            m.set_tracked_hint(tracked_hint);
a8cf6a852f11 rust-dirstate: pass dirstate tracked key from the requirements
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52043
diff changeset
   542
        });
50222
ecd28d89c29e dirstate-v2: add devel config option to control write behavior
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50221
diff changeset
   543
50227
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50222
diff changeset
   544
        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
   545
    }
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   546
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   547
    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
   548
        &self,
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   549
    ) -> 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
   550
        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
   551
    }
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47956
diff changeset
   552
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47956
diff changeset
   553
    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
   554
        &self,
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47956
diff changeset
   555
    ) -> 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
   556
        self.dirstate_map
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49164
diff changeset
   557
            .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
   558
    }
47959
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47958
diff changeset
   559
49090
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49005
diff changeset
   560
    fn new_changelog(&self) -> Result<Changelog, HgError> {
51863
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51188
diff changeset
   561
        Changelog::open(
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51188
diff changeset
   562
            &self.store_vfs(),
52156
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   563
            default_revlog_options(
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   564
                self.config(),
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   565
                self.requirements(),
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   566
                RevlogType::Changelog,
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   567
            )?,
51863
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51188
diff changeset
   568
        )
47958
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47956
diff changeset
   569
    }
47959
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47958
diff changeset
   570
47963
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47961
diff changeset
   571
    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
   572
        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
   573
    }
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47958
diff changeset
   574
47963
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47961
diff changeset
   575
    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
   576
        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
   577
    }
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47958
diff changeset
   578
49090
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49005
diff changeset
   579
    fn new_manifestlog(&self) -> Result<Manifestlog, HgError> {
51188
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51117
diff changeset
   580
        Manifestlog::open(
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51117
diff changeset
   581
            &self.store_vfs(),
52156
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   582
            default_revlog_options(
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   583
                self.config(),
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   584
                self.requirements(),
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   585
                RevlogType::Manifestlog,
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   586
            )?,
51188
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51117
diff changeset
   587
        )
47959
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47958
diff changeset
   588
    }
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47958
diff changeset
   589
47963
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47961
diff changeset
   590
    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
   591
        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
   592
    }
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47958
diff changeset
   593
47963
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47961
diff changeset
   594
    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
   595
        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
   596
    }
47960
cfb6e6699b25 rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents: 47959
diff changeset
   597
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
   598
    /// 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
   599
    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
   600
        &self,
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   601
        node: impl Into<NodePrefix>,
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   602
    ) -> 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
   603
        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
   604
            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
   605
                .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
   606
                .manifest_node()?
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   607
                .into(),
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   608
        )
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   609
    }
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   610
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
   611
    /// 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
   612
    pub fn manifest_for_rev(
47960
cfb6e6699b25 rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents: 47959
diff changeset
   613
        &self,
50974
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50657
diff changeset
   614
        revision: UncheckedRevision,
47960
cfb6e6699b25 rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents: 47959
diff changeset
   615
    ) -> 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
   616
        self.manifestlog()?.data_for_node(
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47964
diff changeset
   617
            self.changelog()?
52290
a3fa37bdb7ec rust: normalize `_for_unchecked_rev` naming among revlogs and the index
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52178
diff changeset
   618
                .data_for_unchecked_rev(revision)?
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
   619
                .manifest_node()?
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47964
diff changeset
   620
                .into(),
47964
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   621
        )
47960
cfb6e6699b25 rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents: 47959
diff changeset
   622
    }
47961
4d2a5ca060e3 rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents: 47960
diff changeset
   623
48510
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48421
diff changeset
   624
    pub fn has_subrepos(&self) -> Result<bool, DirstateError> {
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48421
diff changeset
   625
        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
   626
            Ok(entry.tracked())
48510
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48421
diff changeset
   627
        } else {
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48421
diff changeset
   628
            Ok(false)
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48421
diff changeset
   629
        }
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48421
diff changeset
   630
    }
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48421
diff changeset
   631
47963
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47961
diff changeset
   632
    pub fn filelog(&self, path: &HgPath) -> Result<Filelog, HgError> {
51863
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51188
diff changeset
   633
        Filelog::open(
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51188
diff changeset
   634
            self,
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51188
diff changeset
   635
            path,
52156
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   636
            default_revlog_options(
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   637
                self.config(),
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   638
                self.requirements(),
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   639
                RevlogType::Filelog,
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52050
diff changeset
   640
            )?,
51863
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51188
diff changeset
   641
        )
47961
4d2a5ca060e3 rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents: 47960
diff changeset
   642
    }
48421
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   643
    /// 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
   644
    ///
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   645
    /// The "wlock" must be held while calling this.
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   646
    /// See for example `try_with_wlock_no_wait`.
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   647
    ///
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   648
    /// 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
   649
    /// lock?
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   650
    pub fn write_dirstate(&self) -> Result<(), DirstateError> {
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   651
        let map = self.dirstate_map()?;
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   652
        // 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
   653
        // it’s unset
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   654
        let parents = self.dirstate_parents()?;
50655
1e2c6cda2309 rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
   655
        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
   656
            let (identity, uuid, data_size) =
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   657
                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
   658
            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
   659
            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
   660
            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
   661
50245
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   662
            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
   663
                // 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
   664
                // 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
   665
                // 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
   666
                // 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
   667
                // `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
   668
                // 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
   669
                //
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
                // 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
   671
                // 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
   672
                // (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
   673
                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
   674
                    "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
   675
                );
07d030b38097 rust-dirstate-v2: don't write dirstate if data file has changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50243
diff changeset
   676
                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
   677
            }
07d030b38097 rust-dirstate-v2: don't write dirstate if data file has changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50243
diff changeset
   678
07d030b38097 rust-dirstate-v2: don't write dirstate if data file has changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50243
diff changeset
   679
            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
   680
            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
   681
                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
   682
            } else {
1891086f6c7f dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50211
diff changeset
   683
                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
   684
            };
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
   685
            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
   686
                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
   687
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49146
diff changeset
   688
            // 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
   689
            // deletion.
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49146
diff changeset
   690
            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
   691
                Some(uuid) => {
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49146
diff changeset
   692
                    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
   693
                        .map_err(|_| {
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49146
diff changeset
   694
                            HgError::corrupted(
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49146
diff changeset
   695
                                "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
   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
                        .to_owned();
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49146
diff changeset
   699
                    if append {
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49146
diff changeset
   700
                        (as_str, None)
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49146
diff changeset
   701
                    } else {
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49146
diff changeset
   702
                        (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
   703
                    }
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49146
diff changeset
   704
                }
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49146
diff changeset
   705
                None => (DirstateDocket::new_uid(), None),
48421
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   706
            };
49150
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49146
diff changeset
   707
48421
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   708
            let data_filename = format!("dirstate.{}", uuid);
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   709
            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
   710
            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
   711
            options.write(true);
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
            // 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
   714
            //
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49150
diff changeset
   715
            // - 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
   716
            //   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
   717
            //   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
   718
            //   all such garbage.
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49150
diff changeset
   719
            //
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49150
diff changeset
   720
            // - O_APPEND 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
   721
            //   don't need that.
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49150
diff changeset
   722
            //
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49150
diff changeset
   723
            // - 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
   724
            //   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
   725
            //   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
   726
            //   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
   727
            //
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49150
diff changeset
   728
            if !append {
50211
f5e4248e5bce dirstate: add some debug output when writing the dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50180
diff changeset
   729
                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
   730
                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
   731
            } else {
f5e4248e5bce dirstate: add some debug output when writing the dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50180
diff changeset
   732
                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
   733
            }
49202
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49150
diff changeset
   734
48421
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   735
            let data_size = (|| {
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   736
                // 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
   737
                // returns `ErrorKind::AlreadyExists`? Collision chance of two
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   738
                // random IDs is one in 2**32
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   739
                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
   740
                if append {
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49150
diff changeset
   741
                    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
   742
                }
49202
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49150
diff changeset
   743
                file.write_all(&data)?;
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49150
diff changeset
   744
                file.flush()?;
51117
532e74ad3ff6 rust: run a clippy pass with the latest stable version
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50974
diff changeset
   745
                file.stream_position()
48421
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   746
            })()
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   747
            .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
   748
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
   749
            let packed_dirstate = DirstateDocket::serialize(
48421
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   750
                parents,
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   751
                tree_metadata,
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   752
                data_size,
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   753
                uuid.as_bytes(),
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   754
            )
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   755
            .map_err(|_: std::num::TryFromIntError| {
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   756
                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
   757
            })?;
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
   758
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
   759
            (packed_dirstate, old_uuid)
48421
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   760
        } else {
50245
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   761
            let identity = self.dirstate_identity()?;
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   762
            if identity != map.old_identity() {
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   763
                // 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
   764
                // 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
   765
                // 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
   766
                // `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
   767
                // reading anyway.
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   768
                //
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   769
                // 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
   770
                // without taking the lock.
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   771
                // (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
   772
                log::debug!(
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   773
                    "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
   774
                );
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   775
                return Ok(());
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50244
diff changeset
   776
            }
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
   777
            (map.pack_v1(parents)?, None)
48421
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   778
        };
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
   779
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
   780
        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
   781
        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
   782
        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
   783
            // 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
   784
            // new data file was written.
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
   785
            vfs.unlink(Path::new(&format!("dirstate.{}", uuid)))?;
49146
802e2c25dab8 rust-dirstate-v2: clean up previous data file after the docket is written
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49145
diff changeset
   786
        }
48421
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   787
        Ok(())
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48420
diff changeset
   788
    }
51188
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51117
diff changeset
   789
52031
babfa9ddca0e rust-repo: add a method to get a `Node` from a `Revision` to the `Repo`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52029
diff changeset
   790
    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: 52029
diff changeset
   791
        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: 52029
diff changeset
   792
            .ok()
52290
a3fa37bdb7ec rust: normalize `_for_unchecked_rev` naming among revlogs and the index
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52178
diff changeset
   793
            .and_then(|c| c.node_from_unchecked_rev(rev).copied())
52031
babfa9ddca0e rust-repo: add a method to get a `Node` from a `Revision` to the `Repo`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52029
diff changeset
   794
    }
52032
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52031
diff changeset
   795
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52031
diff changeset
   796
    /// 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: 52031
diff changeset
   797
    ///
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52031
diff changeset
   798
    /// TODO
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52031
diff changeset
   799
    /// 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: 52031
diff changeset
   800
    ///     - 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: 52031
diff changeset
   801
    ///     - 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: 52031
diff changeset
   802
    ///     - 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: 52031
diff changeset
   803
    ///       discarded within the repo context
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52031
diff changeset
   804
    /// See `setparents` in `context.py`.
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52031
diff changeset
   805
    pub fn manually_set_parents(
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52031
diff changeset
   806
        &self,
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52031
diff changeset
   807
        new_parents: DirstateParents,
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52031
diff changeset
   808
    ) -> Result<(), HgError> {
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52031
diff changeset
   809
        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: 52031
diff changeset
   810
        *parents = Some(new_parents);
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52031
diff changeset
   811
        Ok(())
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52031
diff changeset
   812
    }
47958
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47956
diff changeset
   813
}
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47956
diff changeset
   814
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47956
diff changeset
   815
/// 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
   816
///
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47956
diff changeset
   817
/// 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
   818
/// 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
   819
/// 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
   820
/// 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
   821
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
   822
    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
   823
}
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47956
diff changeset
   824
49177
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49164
diff changeset
   825
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
   826
    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
   827
        Self {
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47956
diff changeset
   828
            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
   829
        }
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47956
diff changeset
   830
    }
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47956
diff changeset
   831
48419
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
   832
    fn set(&self, value: T) {
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
   833
        *self.value.borrow_mut() = Some(value)
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
   834
    }
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
   835
49177
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49164
diff changeset
   836
    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
   837
        &self,
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49164
diff changeset
   838
        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
   839
    ) -> 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
   840
        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
   841
        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
   842
            drop(borrowed);
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   843
            // 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
   844
            // 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
   845
            // needed.
49177
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49164
diff changeset
   846
            *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
   847
            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
   848
        }
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   849
        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
   850
    }
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   851
49177
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49164
diff changeset
   852
    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
   853
        &self,
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49164
diff changeset
   854
        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
   855
    ) -> 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
   856
        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
   857
        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
   858
            *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
   859
        }
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
   860
        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
   861
    }
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   862
}