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