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