rust/hg-core/src/config/config.rs
author Raphaël Gomès <rgomes@octobus.net>
Mon, 14 Nov 2022 15:43:05 +0100
changeset 49635 4d729a98673d
parent 49514 e37416d432e9
child 49930 e98fd81bb151
permissions -rw-r--r--
hg-core: make use of `strip_suffix` now that we're using Rust 1.45+
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     1
// config.rs
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     2
//
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     3
// Copyright 2020
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     4
//      Valentin Gatien-Baron,
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     5
//      Raphaël Gomès <rgomes@octobus.net>
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     6
//
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     7
// This software may be used and distributed according to the terms of the
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     8
// GNU General Public License version 2 or any later version.
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     9
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    10
use super::layer;
46602
a687a7f27951 rust: Move config value parsing functions to a new module
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
    11
use super::values;
46447
0cb1b02228a6 rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
    12
use crate::config::layer::{
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
    13
    ConfigError, ConfigLayer, ConfigOrigin, ConfigValue,
46447
0cb1b02228a6 rust: use HgError in ConfigError
Simon Sapin <simon.sapin@octobus.net>
parents: 46446
diff changeset
    14
};
49513
467d9df98c68 rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49512
diff changeset
    15
use crate::config::plain_info::PlainInfo;
46596
d2e61f00ee9d rust: Introduce a get_bytes_from_os_str utility function
Simon Sapin <simon.sapin@octobus.net>
parents: 46504
diff changeset
    16
use crate::utils::files::get_bytes_from_os_str;
46499
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    17
use format_bytes::{write_bytes, DisplayBytes};
46733
1bac7764ceef rhg: Fall back to Python if unsupported extensions are enabled
Simon Sapin <simon.sapin@octobus.net>
parents: 46732
diff changeset
    18
use std::collections::HashSet;
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
    19
use std::env;
46797
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    20
use std::fmt;
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
    21
use std::path::{Path, PathBuf};
46597
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
    22
use std::str;
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    23
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
    24
use crate::errors::{HgResultExt, IoResultExt};
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    25
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    26
/// Holds the config values for the current repository
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    27
/// TODO update this docstring once we support more sources
46741
25e3dac511f0 rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents: 46734
diff changeset
    28
#[derive(Clone)]
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    29
pub struct Config {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    30
    layers: Vec<layer::ConfigLayer>,
49512
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
    31
    plain: PlainInfo,
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    32
}
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    33
46499
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    34
impl DisplayBytes for Config {
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    35
    fn display_bytes(
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    36
        &self,
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    37
        out: &mut dyn std::io::Write,
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    38
    ) -> std::io::Result<()> {
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    39
        for (index, layer) in self.layers.iter().rev().enumerate() {
46499
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    40
            write_bytes!(
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    41
                out,
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    42
                b"==== Layer {} (trusted: {}) ====\n{}",
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    43
                index,
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    44
                if layer.trusted {
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    45
                    &b"yes"[..]
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    46
                } else {
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    47
                    &b"no"[..]
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    48
                },
eace48b4a786 rust: Use the DisplayBytes trait in config printing
Simon Sapin <simon.sapin@octobus.net>
parents: 46486
diff changeset
    49
                layer
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    50
            )?;
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    51
        }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    52
        Ok(())
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    53
    }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    54
}
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    55
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    56
pub enum ConfigSource {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    57
    /// Absolute path to a config file
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    58
    AbsPath(PathBuf),
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    59
    /// Already parsed (from the CLI, env, Python resources, etc.)
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    60
    Parsed(layer::ConfigLayer),
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    61
}
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    62
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
    63
#[derive(Debug)]
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
    64
pub struct ConfigValueParseError {
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
    65
    pub origin: ConfigOrigin,
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
    66
    pub line: Option<usize>,
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
    67
    pub section: Vec<u8>,
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
    68
    pub item: Vec<u8>,
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
    69
    pub value: Vec<u8>,
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
    70
    pub expected_type: &'static str,
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
    71
}
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
    72
46797
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    73
impl fmt::Display for ConfigValueParseError {
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    74
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    75
        // TODO: add origin and line number information, here and in
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    76
        // corresponding python code
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    77
        write!(
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    78
            f,
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    79
            "config error: {}.{} is not a {} ('{}')",
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    80
            String::from_utf8_lossy(&self.section),
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    81
            String::from_utf8_lossy(&self.item),
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    82
            self.expected_type,
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    83
            String::from_utf8_lossy(&self.value)
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    84
        )
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    85
    }
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    86
}
bcdcb4423ae3 rhg: Add more conversions between error types
Simon Sapin <simon.sapin@octobus.net>
parents: 46741
diff changeset
    87
49513
467d9df98c68 rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49512
diff changeset
    88
/// Returns true if the config item is disabled by PLAIN or PLAINEXCEPT
49512
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
    89
fn should_ignore(plain: &PlainInfo, section: &[u8], item: &[u8]) -> bool {
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
    90
    // duplication with [_applyconfig] in [ui.py],
49513
467d9df98c68 rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49512
diff changeset
    91
    if !plain.is_plain() {
49512
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
    92
        return false;
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
    93
    }
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
    94
    if section == b"alias" {
49513
467d9df98c68 rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49512
diff changeset
    95
        return plain.plainalias();
49512
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
    96
    }
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
    97
    if section == b"revsetalias" {
49513
467d9df98c68 rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49512
diff changeset
    98
        return plain.plainrevsetalias();
49512
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
    99
    }
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   100
    if section == b"templatealias" {
49513
467d9df98c68 rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49512
diff changeset
   101
        return plain.plaintemplatealias();
49512
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   102
    }
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   103
    if section == b"ui" {
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   104
        let to_delete: &[&[u8]] = &[
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   105
            b"debug",
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   106
            b"fallbackencoding",
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   107
            b"quiet",
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   108
            b"slash",
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   109
            b"logtemplate",
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   110
            b"message-output",
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   111
            b"statuscopies",
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   112
            b"style",
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   113
            b"traceback",
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   114
            b"verbose",
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   115
        ];
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   116
        return to_delete.contains(&item);
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   117
    }
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   118
    let sections_to_delete: &[&[u8]] =
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   119
        &[b"defaults", b"commands", b"command-templates"];
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   120
    return sections_to_delete.contains(&section);
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   121
}
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   122
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   123
impl Config {
48730
1aaf11e35aec rhg: Pass a &Config to Ui::new
Simon Sapin <simon.sapin@octobus.net>
parents: 48451
diff changeset
   124
    /// The configuration to use when printing configuration-loading errors
1aaf11e35aec rhg: Pass a &Config to Ui::new
Simon Sapin <simon.sapin@octobus.net>
parents: 48451
diff changeset
   125
    pub fn empty() -> Self {
49512
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   126
        Self {
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   127
            layers: Vec::new(),
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   128
            plain: PlainInfo::empty(),
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   129
        }
48730
1aaf11e35aec rhg: Pass a &Config to Ui::new
Simon Sapin <simon.sapin@octobus.net>
parents: 48451
diff changeset
   130
    }
1aaf11e35aec rhg: Pass a &Config to Ui::new
Simon Sapin <simon.sapin@octobus.net>
parents: 48451
diff changeset
   131
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   132
    /// Load system and user configuration from various files.
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   133
    ///
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   134
    /// This is also affected by some environment variables.
47406
3237ed4dcda4 rhg: split non_repo_config and `--config` loading in different functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47189
diff changeset
   135
    pub fn load_non_repo() -> Result<Self, ConfigError> {
49512
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   136
        let mut config = Self::empty();
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   137
        let opt_rc_path = env::var_os("HGRCPATH");
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   138
        // HGRCPATH replaces system config
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   139
        if opt_rc_path.is_none() {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   140
            config.add_system_config()?
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   141
        }
46722
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   142
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   143
        config.add_for_environment_variable("EDITOR", b"ui", b"editor");
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   144
        config.add_for_environment_variable("VISUAL", b"ui", b"editor");
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   145
        config.add_for_environment_variable("PAGER", b"pager", b"pager");
46722
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   146
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   147
        // These are set by `run-tests.py --rhg` to enable fallback for the
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   148
        // entire test suite. Alternatives would be setting configuration
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   149
        // through `$HGRCPATH` but some tests override that, or changing the
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   150
        // `hg` shell alias to include `--config` but that disrupts tests that
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   151
        // print command lines and check expected output.
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   152
        config.add_for_environment_variable(
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   153
            "RHG_ON_UNSUPPORTED",
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   154
            b"rhg",
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   155
            b"on-unsupported",
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   156
        );
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   157
        config.add_for_environment_variable(
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   158
            "RHG_FALLBACK_EXECUTABLE",
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   159
            b"rhg",
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   160
            b"fallback-executable",
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   161
        );
08a35cec14d4 rhg: Add environment variables for fallback configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46602
diff changeset
   162
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   163
        // HGRCPATH replaces user config
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   164
        if opt_rc_path.is_none() {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   165
            config.add_user_config()?
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   166
        }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   167
        if let Some(rc_path) = &opt_rc_path {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   168
            for path in env::split_paths(rc_path) {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   169
                if !path.as_os_str().is_empty() {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   170
                    if path.is_dir() {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   171
                        config.add_trusted_dir(&path)?
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   172
                    } else {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   173
                        config.add_trusted_file(&path)?
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   174
                    }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   175
                }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   176
            }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   177
        }
47406
3237ed4dcda4 rhg: split non_repo_config and `--config` loading in different functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47189
diff changeset
   178
        Ok(config)
3237ed4dcda4 rhg: split non_repo_config and `--config` loading in different functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47189
diff changeset
   179
    }
3237ed4dcda4 rhg: split non_repo_config and `--config` loading in different functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47189
diff changeset
   180
48732
d4a5c2197208 rhg: Add parsing for the --color global CLI argument
Simon Sapin <simon.sapin@octobus.net>
parents: 48730
diff changeset
   181
    pub fn load_cli_args(
47406
3237ed4dcda4 rhg: split non_repo_config and `--config` loading in different functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47189
diff changeset
   182
        &mut self,
3237ed4dcda4 rhg: split non_repo_config and `--config` loading in different functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47189
diff changeset
   183
        cli_config_args: impl IntoIterator<Item = impl AsRef<[u8]>>,
48732
d4a5c2197208 rhg: Add parsing for the --color global CLI argument
Simon Sapin <simon.sapin@octobus.net>
parents: 48730
diff changeset
   184
        color_arg: Option<Vec<u8>>,
47406
3237ed4dcda4 rhg: split non_repo_config and `--config` loading in different functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47189
diff changeset
   185
    ) -> Result<(), ConfigError> {
46504
2e5dd18d6dc3 rhg: Add support for --config CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46499
diff changeset
   186
        if let Some(layer) = ConfigLayer::parse_cli_args(cli_config_args)? {
47406
3237ed4dcda4 rhg: split non_repo_config and `--config` loading in different functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47189
diff changeset
   187
            self.layers.push(layer)
46504
2e5dd18d6dc3 rhg: Add support for --config CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46499
diff changeset
   188
        }
48732
d4a5c2197208 rhg: Add parsing for the --color global CLI argument
Simon Sapin <simon.sapin@octobus.net>
parents: 48730
diff changeset
   189
        if let Some(arg) = color_arg {
d4a5c2197208 rhg: Add parsing for the --color global CLI argument
Simon Sapin <simon.sapin@octobus.net>
parents: 48730
diff changeset
   190
            let mut layer = ConfigLayer::new(ConfigOrigin::CommandLineColor);
d4a5c2197208 rhg: Add parsing for the --color global CLI argument
Simon Sapin <simon.sapin@octobus.net>
parents: 48730
diff changeset
   191
            layer.add(b"ui"[..].into(), b"color"[..].into(), arg, None);
d4a5c2197208 rhg: Add parsing for the --color global CLI argument
Simon Sapin <simon.sapin@octobus.net>
parents: 48730
diff changeset
   192
            self.layers.push(layer)
d4a5c2197208 rhg: Add parsing for the --color global CLI argument
Simon Sapin <simon.sapin@octobus.net>
parents: 48730
diff changeset
   193
        }
47406
3237ed4dcda4 rhg: split non_repo_config and `--config` loading in different functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47189
diff changeset
   194
        Ok(())
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   195
    }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   196
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   197
    fn add_trusted_dir(&mut self, path: &Path) -> Result<(), ConfigError> {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   198
        if let Some(entries) = std::fs::read_dir(path)
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   199
            .when_reading_file(path)
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   200
            .io_not_found_as_none()?
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   201
        {
46732
60fe9ebae29b rhg: Sort config files when adding a directory
Simon Sapin <simon.sapin@octobus.net>
parents: 46722
diff changeset
   202
            let mut file_paths = entries
60fe9ebae29b rhg: Sort config files when adding a directory
Simon Sapin <simon.sapin@octobus.net>
parents: 46722
diff changeset
   203
                .map(|result| {
60fe9ebae29b rhg: Sort config files when adding a directory
Simon Sapin <simon.sapin@octobus.net>
parents: 46722
diff changeset
   204
                    result.when_reading_file(path).map(|entry| entry.path())
60fe9ebae29b rhg: Sort config files when adding a directory
Simon Sapin <simon.sapin@octobus.net>
parents: 46722
diff changeset
   205
                })
60fe9ebae29b rhg: Sort config files when adding a directory
Simon Sapin <simon.sapin@octobus.net>
parents: 46722
diff changeset
   206
                .collect::<Result<Vec<_>, _>>()?;
60fe9ebae29b rhg: Sort config files when adding a directory
Simon Sapin <simon.sapin@octobus.net>
parents: 46722
diff changeset
   207
            file_paths.sort();
60fe9ebae29b rhg: Sort config files when adding a directory
Simon Sapin <simon.sapin@octobus.net>
parents: 46722
diff changeset
   208
            for file_path in &file_paths {
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   209
                if file_path.extension() == Some(std::ffi::OsStr::new("rc")) {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   210
                    self.add_trusted_file(&file_path)?
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   211
                }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   212
            }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   213
        }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   214
        Ok(())
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   215
    }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   216
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   217
    fn add_trusted_file(&mut self, path: &Path) -> Result<(), ConfigError> {
46599
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   218
        if let Some(data) = std::fs::read(path)
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   219
            .when_reading_file(path)
1f55cd5b292f rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents: 46598
diff changeset
   220
            .io_not_found_as_none()?
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   221
        {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   222
            self.layers.extend(ConfigLayer::parse(path, &data)?)
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   223
        }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   224
        Ok(())
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   225
    }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   226
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   227
    fn add_for_environment_variable(
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   228
        &mut self,
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   229
        var: &str,
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   230
        section: &[u8],
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   231
        key: &[u8],
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   232
    ) {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   233
        if let Some(value) = env::var_os(var) {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   234
            let origin = layer::ConfigOrigin::Environment(var.into());
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   235
            let mut layer = ConfigLayer::new(origin);
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   236
            layer.add(
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   237
                section.to_owned(),
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   238
                key.to_owned(),
46596
d2e61f00ee9d rust: Introduce a get_bytes_from_os_str utility function
Simon Sapin <simon.sapin@octobus.net>
parents: 46504
diff changeset
   239
                get_bytes_from_os_str(value),
46483
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   240
                None,
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   241
            );
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   242
            self.layers.push(layer)
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   243
        }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   244
    }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   245
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   246
    #[cfg(unix)] // TODO: other platforms
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   247
    fn add_system_config(&mut self) -> Result<(), ConfigError> {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   248
        let mut add_for_prefix = |prefix: &Path| -> Result<(), ConfigError> {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   249
            let etc = prefix.join("etc").join("mercurial");
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   250
            self.add_trusted_file(&etc.join("hgrc"))?;
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   251
            self.add_trusted_dir(&etc.join("hgrc.d"))
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   252
        };
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   253
        let root = Path::new("/");
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   254
        // TODO: use `std::env::args_os().next().unwrap()` a.k.a. argv[0]
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   255
        // instead? TODO: can this be a relative path?
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   256
        let hg = crate::utils::current_exe()?;
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   257
        // TODO: this order (per-installation then per-system) matches
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   258
        // `systemrcpath()` in `mercurial/scmposix.py`, but
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   259
        // `mercurial/helptext/config.txt` suggests it should be reversed
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   260
        if let Some(installation_prefix) = hg.parent().and_then(Path::parent) {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   261
            if installation_prefix != root {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   262
                add_for_prefix(&installation_prefix)?
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   263
            }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   264
        }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   265
        add_for_prefix(root)?;
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   266
        Ok(())
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   267
    }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   268
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   269
    #[cfg(unix)] // TODO: other plateforms
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   270
    fn add_user_config(&mut self) -> Result<(), ConfigError> {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   271
        let opt_home = home::home_dir();
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   272
        if let Some(home) = &opt_home {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   273
            self.add_trusted_file(&home.join(".hgrc"))?
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   274
        }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   275
        let darwin = cfg!(any(target_os = "macos", target_os = "ios"));
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   276
        if !darwin {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   277
            if let Some(config_home) = env::var_os("XDG_CONFIG_HOME")
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   278
                .map(PathBuf::from)
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   279
                .or_else(|| opt_home.map(|home| home.join(".config")))
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   280
            {
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   281
                self.add_trusted_file(&config_home.join("hg").join("hgrc"))?
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   282
            }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   283
        }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   284
        Ok(())
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   285
    }
2845892dd489 rust: Parse system and user configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46481
diff changeset
   286
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   287
    /// Loads in order, which means that the precedence is the same
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   288
    /// as the order of `sources`.
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   289
    pub fn load_from_explicit_sources(
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   290
        sources: Vec<ConfigSource>,
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   291
    ) -> Result<Self, ConfigError> {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   292
        let mut layers = vec![];
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   293
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   294
        for source in sources.into_iter() {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   295
            match source {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   296
                ConfigSource::Parsed(c) => layers.push(c),
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   297
                ConfigSource::AbsPath(c) => {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   298
                    // TODO check if it should be trusted
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   299
                    // mercurial/ui.py:427
46481
0d734c0ae1cf rust: replace read_whole_file with std::fs::read
Simon Sapin <simon.sapin@octobus.net>
parents: 46447
diff changeset
   300
                    let data = match std::fs::read(&c) {
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   301
                        Err(_) => continue, // same as the python code
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   302
                        Ok(data) => data,
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   303
                    };
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   304
                    layers.extend(ConfigLayer::parse(&c, &data)?)
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   305
                }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   306
            }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   307
        }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   308
49512
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   309
        Ok(Config {
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   310
            layers,
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   311
            plain: PlainInfo::empty(),
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   312
        })
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   313
    }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   314
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   315
    /// Loads the per-repository config into a new `Config` which is combined
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   316
    /// with `self`.
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   317
    pub(crate) fn combine_with_repo(
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   318
        &self,
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   319
        repo_config_files: &[PathBuf],
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   320
    ) -> Result<Self, ConfigError> {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   321
        let (cli_layers, other_layers) = self
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   322
            .layers
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   323
            .iter()
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   324
            .cloned()
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   325
            .partition(ConfigLayer::is_from_command_line);
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   326
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   327
        let mut repo_config = Self {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   328
            layers: other_layers,
49512
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   329
            plain: PlainInfo::empty(),
46486
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   330
        };
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   331
        for path in repo_config_files {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   332
            // TODO: check if this file should be trusted:
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   333
            // `mercurial/ui.py:427`
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   334
            repo_config.add_trusted_file(path)?;
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   335
        }
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   336
        repo_config.layers.extend(cli_layers);
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46483
diff changeset
   337
        Ok(repo_config)
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   338
    }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   339
49512
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   340
    pub fn apply_plain(&mut self, plain: PlainInfo) {
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   341
        self.plain = plain;
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   342
    }
6939d5ed20e0 rhg: central treatment of PLAIN and PLAINEXCEPT
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48735
diff changeset
   343
46597
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   344
    fn get_parse<'config, T: 'config>(
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   345
        &'config self,
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   346
        section: &[u8],
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   347
        item: &[u8],
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   348
        expected_type: &'static str,
46597
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   349
        parse: impl Fn(&'config [u8]) -> Option<T>,
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   350
    ) -> Result<Option<T>, ConfigValueParseError> {
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   351
        match self.get_inner(&section, &item) {
46597
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   352
            Some((layer, v)) => match parse(&v.bytes) {
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   353
                Some(b) => Ok(Some(b)),
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   354
                None => Err(ConfigValueParseError {
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   355
                    origin: layer.origin.to_owned(),
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   356
                    line: v.line,
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   357
                    value: v.bytes.to_owned(),
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   358
                    section: section.to_owned(),
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   359
                    item: item.to_owned(),
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   360
                    expected_type,
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   361
                }),
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   362
            },
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   363
            None => Ok(None),
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   364
        }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   365
    }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   366
46597
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   367
    /// Returns an `Err` if the first value found is not a valid UTF-8 string.
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   368
    /// Otherwise, returns an `Ok(value)` if found, or `None`.
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   369
    pub fn get_str(
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   370
        &self,
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   371
        section: &[u8],
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   372
        item: &[u8],
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   373
    ) -> Result<Option<&str>, ConfigValueParseError> {
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   374
        self.get_parse(section, item, "ASCII or UTF-8 string", |value| {
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   375
            str::from_utf8(value).ok()
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   376
        })
46597
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   377
    }
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   378
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   379
    /// Returns an `Err` if the first value found is not a valid unsigned
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   380
    /// integer. Otherwise, returns an `Ok(value)` if found, or `None`.
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   381
    pub fn get_u32(
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   382
        &self,
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   383
        section: &[u8],
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   384
        item: &[u8],
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   385
    ) -> Result<Option<u32>, ConfigValueParseError> {
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   386
        self.get_parse(section, item, "valid integer", |value| {
46597
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   387
            str::from_utf8(value).ok()?.parse().ok()
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   388
        })
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   389
    }
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   390
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   391
    /// Returns an `Err` if the first value found is not a valid file size
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   392
    /// value such as `30` (default unit is bytes), `7 MB`, or `42.5 kb`.
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   393
    /// Otherwise, returns an `Ok(value_in_bytes)` if found, or `None`.
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   394
    pub fn get_byte_size(
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   395
        &self,
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   396
        section: &[u8],
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   397
        item: &[u8],
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   398
    ) -> Result<Option<u64>, ConfigValueParseError> {
46602
a687a7f27951 rust: Move config value parsing functions to a new module
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   399
        self.get_parse(section, item, "byte quantity", values::parse_byte_size)
46597
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   400
    }
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   401
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   402
    /// Returns an `Err` if the first value found is not a valid boolean.
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   403
    /// Otherwise, returns an `Ok(option)`, where `option` is the boolean if
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   404
    /// found, or `None`.
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   405
    pub fn get_option(
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   406
        &self,
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   407
        section: &[u8],
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   408
        item: &[u8],
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   409
    ) -> Result<Option<bool>, ConfigValueParseError> {
46602
a687a7f27951 rust: Move config value parsing functions to a new module
Simon Sapin <simon.sapin@octobus.net>
parents: 46599
diff changeset
   410
        self.get_parse(section, item, "boolean", values::parse_bool)
46597
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   411
    }
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   412
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   413
    /// Returns the corresponding boolean in the config. Returns `Ok(false)`
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   414
    /// if the value is not found, an `Err` if it's not a valid boolean.
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   415
    pub fn get_bool(
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   416
        &self,
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   417
        section: &[u8],
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   418
        item: &[u8],
46598
bc08c2331f99 rust: Add a `ConfigValueParseError` variant to common errors
Simon Sapin <simon.sapin@octobus.net>
parents: 46597
diff changeset
   419
    ) -> Result<bool, ConfigValueParseError> {
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   420
        Ok(self.get_option(section, item)?.unwrap_or(false))
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   421
    }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   422
48414
1d940d76571b rust: add function to check if an extension is enabled
Raphaël Gomès <rgomes@octobus.net>
parents: 48339
diff changeset
   423
    /// Returns `true` if the extension is enabled, `false` otherwise
1d940d76571b rust: add function to check if an extension is enabled
Raphaël Gomès <rgomes@octobus.net>
parents: 48339
diff changeset
   424
    pub fn is_extension_enabled(&self, extension: &[u8]) -> bool {
1d940d76571b rust: add function to check if an extension is enabled
Raphaël Gomès <rgomes@octobus.net>
parents: 48339
diff changeset
   425
        let value = self.get(b"extensions", extension);
1d940d76571b rust: add function to check if an extension is enabled
Raphaël Gomès <rgomes@octobus.net>
parents: 48339
diff changeset
   426
        match value {
1d940d76571b rust: add function to check if an extension is enabled
Raphaël Gomès <rgomes@octobus.net>
parents: 48339
diff changeset
   427
            Some(c) => !c.starts_with(b"!"),
1d940d76571b rust: add function to check if an extension is enabled
Raphaël Gomès <rgomes@octobus.net>
parents: 48339
diff changeset
   428
            None => false,
1d940d76571b rust: add function to check if an extension is enabled
Raphaël Gomès <rgomes@octobus.net>
parents: 48339
diff changeset
   429
        }
1d940d76571b rust: add function to check if an extension is enabled
Raphaël Gomès <rgomes@octobus.net>
parents: 48339
diff changeset
   430
    }
1d940d76571b rust: add function to check if an extension is enabled
Raphaël Gomès <rgomes@octobus.net>
parents: 48339
diff changeset
   431
47950
6961eca0b3ee rhg: Port Python’s `ui.configlist` as `Config::get_list`
Simon Sapin <simon.sapin@octobus.net>
parents: 47406
diff changeset
   432
    /// If there is an `item` value in `section`, parse and return a list of
6961eca0b3ee rhg: Port Python’s `ui.configlist` as `Config::get_list`
Simon Sapin <simon.sapin@octobus.net>
parents: 47406
diff changeset
   433
    /// byte strings.
6961eca0b3ee rhg: Port Python’s `ui.configlist` as `Config::get_list`
Simon Sapin <simon.sapin@octobus.net>
parents: 47406
diff changeset
   434
    pub fn get_list(
6961eca0b3ee rhg: Port Python’s `ui.configlist` as `Config::get_list`
Simon Sapin <simon.sapin@octobus.net>
parents: 47406
diff changeset
   435
        &self,
6961eca0b3ee rhg: Port Python’s `ui.configlist` as `Config::get_list`
Simon Sapin <simon.sapin@octobus.net>
parents: 47406
diff changeset
   436
        section: &[u8],
6961eca0b3ee rhg: Port Python’s `ui.configlist` as `Config::get_list`
Simon Sapin <simon.sapin@octobus.net>
parents: 47406
diff changeset
   437
        item: &[u8],
6961eca0b3ee rhg: Port Python’s `ui.configlist` as `Config::get_list`
Simon Sapin <simon.sapin@octobus.net>
parents: 47406
diff changeset
   438
    ) -> Option<Vec<Vec<u8>>> {
6961eca0b3ee rhg: Port Python’s `ui.configlist` as `Config::get_list`
Simon Sapin <simon.sapin@octobus.net>
parents: 47406
diff changeset
   439
        self.get(section, item).map(values::parse_list)
6961eca0b3ee rhg: Port Python’s `ui.configlist` as `Config::get_list`
Simon Sapin <simon.sapin@octobus.net>
parents: 47406
diff changeset
   440
    }
6961eca0b3ee rhg: Port Python’s `ui.configlist` as `Config::get_list`
Simon Sapin <simon.sapin@octobus.net>
parents: 47406
diff changeset
   441
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   442
    /// Returns the raw value bytes of the first one found, or `None`.
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   443
    pub fn get(&self, section: &[u8], item: &[u8]) -> Option<&[u8]> {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   444
        self.get_inner(section, item)
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   445
            .map(|(_, value)| value.bytes.as_ref())
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   446
    }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   447
48733
39c447e03dbc rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents: 48732
diff changeset
   448
    /// Returns the raw value bytes of the first one found, or `None`.
39c447e03dbc rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents: 48732
diff changeset
   449
    pub fn get_with_origin(
39c447e03dbc rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents: 48732
diff changeset
   450
        &self,
39c447e03dbc rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents: 48732
diff changeset
   451
        section: &[u8],
39c447e03dbc rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents: 48732
diff changeset
   452
        item: &[u8],
39c447e03dbc rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents: 48732
diff changeset
   453
    ) -> Option<(&[u8], &ConfigOrigin)> {
39c447e03dbc rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents: 48732
diff changeset
   454
        self.get_inner(section, item)
39c447e03dbc rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents: 48732
diff changeset
   455
            .map(|(layer, value)| (value.bytes.as_ref(), &layer.origin))
39c447e03dbc rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents: 48732
diff changeset
   456
    }
39c447e03dbc rhg: Add support for colored output
Simon Sapin <simon.sapin@octobus.net>
parents: 48732
diff changeset
   457
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   458
    /// Returns the layer and the value of the first one found, or `None`.
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   459
    fn get_inner(
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   460
        &self,
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   461
        section: &[u8],
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   462
        item: &[u8],
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   463
    ) -> Option<(&ConfigLayer, &ConfigValue)> {
49513
467d9df98c68 rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49512
diff changeset
   464
        // Filter out the config items that are hidden by [PLAIN].
467d9df98c68 rhg: centralize PlainInfo
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49512
diff changeset
   465
        // This differs from python hg where we delete them from the config.
49514
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   466
        let should_ignore = should_ignore(&self.plain, &section, &item);
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   467
        for layer in self.layers.iter().rev() {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   468
            if !layer.trusted {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   469
                continue;
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   470
            }
49514
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   471
            //The [PLAIN] config should not affect the defaults.
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   472
            //
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   473
            // However, PLAIN should also affect the "tweaked" defaults (unless
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   474
            // "tweakdefault" is part of "HGPLAINEXCEPT").
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   475
            //
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   476
            // In practice the tweak-default layer is only added when it is
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   477
            // relevant, so we can safely always take it into
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   478
            // account here.
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   479
            if should_ignore && !(layer.origin == ConfigOrigin::Tweakdefaults)
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   480
            {
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   481
                continue;
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   482
            }
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   483
            if let Some(v) = layer.get(&section, &item) {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   484
                return Some((&layer, v));
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   485
            }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   486
        }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   487
        None
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   488
    }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   489
46733
1bac7764ceef rhg: Fall back to Python if unsupported extensions are enabled
Simon Sapin <simon.sapin@octobus.net>
parents: 46732
diff changeset
   490
    /// Return all keys defined for the given section
1bac7764ceef rhg: Fall back to Python if unsupported extensions are enabled
Simon Sapin <simon.sapin@octobus.net>
parents: 46732
diff changeset
   491
    pub fn get_section_keys(&self, section: &[u8]) -> HashSet<&[u8]> {
1bac7764ceef rhg: Fall back to Python if unsupported extensions are enabled
Simon Sapin <simon.sapin@octobus.net>
parents: 46732
diff changeset
   492
        self.layers
1bac7764ceef rhg: Fall back to Python if unsupported extensions are enabled
Simon Sapin <simon.sapin@octobus.net>
parents: 46732
diff changeset
   493
            .iter()
1bac7764ceef rhg: Fall back to Python if unsupported extensions are enabled
Simon Sapin <simon.sapin@octobus.net>
parents: 46732
diff changeset
   494
            .flat_map(|layer| layer.iter_keys(section))
1bac7764ceef rhg: Fall back to Python if unsupported extensions are enabled
Simon Sapin <simon.sapin@octobus.net>
parents: 46732
diff changeset
   495
            .collect()
1bac7764ceef rhg: Fall back to Python if unsupported extensions are enabled
Simon Sapin <simon.sapin@octobus.net>
parents: 46732
diff changeset
   496
    }
1bac7764ceef rhg: Fall back to Python if unsupported extensions are enabled
Simon Sapin <simon.sapin@octobus.net>
parents: 46732
diff changeset
   497
48339
a2e278b5e265 rhg: [encode] and [decode] config sections are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48335
diff changeset
   498
    /// Returns whether any key is defined in the given section
a2e278b5e265 rhg: [encode] and [decode] config sections are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48335
diff changeset
   499
    pub fn has_non_empty_section(&self, section: &[u8]) -> bool {
a2e278b5e265 rhg: [encode] and [decode] config sections are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48335
diff changeset
   500
        self.layers
a2e278b5e265 rhg: [encode] and [decode] config sections are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48335
diff changeset
   501
            .iter()
a2e278b5e265 rhg: [encode] and [decode] config sections are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48335
diff changeset
   502
            .any(|layer| layer.has_non_empty_section(section))
a2e278b5e265 rhg: [encode] and [decode] config sections are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48335
diff changeset
   503
    }
a2e278b5e265 rhg: [encode] and [decode] config sections are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48335
diff changeset
   504
48451
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   505
    /// Yields (key, value) pairs for everything in the given section
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   506
    pub fn iter_section<'a>(
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   507
        &'a self,
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   508
        section: &'a [u8],
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   509
    ) -> impl Iterator<Item = (&[u8], &[u8])> + 'a {
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   510
        // TODO: Use `Iterator`’s `.peekable()` when its `peek_mut` is
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   511
        // available:
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   512
        // https://doc.rust-lang.org/nightly/std/iter/struct.Peekable.html#method.peek_mut
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   513
        struct Peekable<I: Iterator> {
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   514
            iter: I,
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   515
            /// Remember a peeked value, even if it was None.
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   516
            peeked: Option<Option<I::Item>>,
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   517
        }
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   518
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   519
        impl<I: Iterator> Peekable<I> {
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   520
            fn new(iter: I) -> Self {
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   521
                Self { iter, peeked: None }
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   522
            }
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   523
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   524
            fn next(&mut self) {
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   525
                self.peeked = None
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   526
            }
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   527
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   528
            fn peek_mut(&mut self) -> Option<&mut I::Item> {
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   529
                let iter = &mut self.iter;
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   530
                self.peeked.get_or_insert_with(|| iter.next()).as_mut()
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   531
            }
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   532
        }
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   533
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   534
        // Deduplicate keys redefined in multiple layers
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   535
        let mut keys_already_seen = HashSet::new();
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   536
        let mut key_is_new =
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   537
            move |&(key, _value): &(&'a [u8], &'a [u8])| -> bool {
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   538
                keys_already_seen.insert(key)
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   539
            };
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   540
        // This is similar to `flat_map` + `filter_map`, except with a single
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   541
        // closure that owns `key_is_new` (and therefore the
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   542
        // `keys_already_seen` set):
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   543
        let mut layer_iters = Peekable::new(
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   544
            self.layers
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   545
                .iter()
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   546
                .rev()
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   547
                .map(move |layer| layer.iter_section(section)),
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   548
        );
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   549
        std::iter::from_fn(move || loop {
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   550
            if let Some(pair) = layer_iters.peek_mut()?.find(&mut key_is_new) {
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   551
                return Some(pair);
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   552
            } else {
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   553
                layer_iters.next();
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   554
            }
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   555
        })
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   556
    }
4a983b69e519 rhg: Add support for ui.ignore and ui.ignore.* config
Simon Sapin <simon.sapin@octobus.net>
parents: 48414
diff changeset
   557
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   558
    /// Get raw values bytes from all layers (even untrusted ones) in order
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   559
    /// of precedence.
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   560
    #[cfg(test)]
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   561
    fn get_all(&self, section: &[u8], item: &[u8]) -> Vec<&[u8]> {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   562
        let mut res = vec![];
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   563
        for layer in self.layers.iter().rev() {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   564
            if let Some(v) = layer.get(&section, &item) {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   565
                res.push(v.bytes.as_ref());
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   566
            }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   567
        }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   568
        res
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   569
    }
49514
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   570
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   571
    // a config layer that's introduced by ui.tweakdefaults
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   572
    fn tweakdefaults_layer() -> ConfigLayer {
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   573
        let mut layer = ConfigLayer::new(ConfigOrigin::Tweakdefaults);
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   574
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   575
        let mut add = |section: &[u8], item: &[u8], value: &[u8]| {
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   576
            layer.add(
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   577
                section[..].into(),
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   578
                item[..].into(),
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   579
                value[..].into(),
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   580
                None,
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   581
            );
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   582
        };
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   583
        // duplication of [tweakrc] from [ui.py]
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   584
        add(b"ui", b"rollback", b"False");
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   585
        add(b"ui", b"statuscopies", b"yes");
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   586
        add(b"ui", b"interface", b"curses");
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   587
        add(b"ui", b"relative-paths", b"yes");
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   588
        add(b"commands", b"grep.all-files", b"True");
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   589
        add(b"commands", b"update.check", b"noconflict");
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   590
        add(b"commands", b"status.verbose", b"True");
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   591
        add(b"commands", b"resolve.explicit-re-merge", b"True");
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   592
        add(b"git", b"git", b"1");
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   593
        add(b"git", b"showfunc", b"1");
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   594
        add(b"git", b"word-diff", b"1");
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   595
        return layer;
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   596
    }
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   597
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   598
    // introduce the tweaked defaults as implied by ui.tweakdefaults
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   599
    pub fn tweakdefaults<'a>(&mut self) -> () {
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   600
        self.layers.insert(0, Config::tweakdefaults_layer());
e37416d432e9 rhg: support tweakdefaults
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49513
diff changeset
   601
    }
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   602
}
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   603
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   604
#[cfg(test)]
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   605
mod tests {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   606
    use super::*;
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   607
    use pretty_assertions::assert_eq;
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   608
    use std::fs::File;
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   609
    use std::io::Write;
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   610
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   611
    #[test]
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   612
    fn test_include_layer_ordering() {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   613
        let tmpdir = tempfile::tempdir().unwrap();
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   614
        let tmpdir_path = tmpdir.path();
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   615
        let mut included_file =
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   616
            File::create(&tmpdir_path.join("included.rc")).unwrap();
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   617
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   618
        included_file.write_all(b"[section]\nitem=value1").unwrap();
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   619
        let base_config_path = tmpdir_path.join("base.rc");
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   620
        let mut config_file = File::create(&base_config_path).unwrap();
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   621
        let data =
46597
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   622
            b"[section]\nitem=value0\n%include included.rc\nitem=value2\n\
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   623
              [section2]\ncount = 4\nsize = 1.5 KB\nnot-count = 1.5\nnot-size = 1 ub";
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   624
        config_file.write_all(data).unwrap();
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   625
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   626
        let sources = vec![ConfigSource::AbsPath(base_config_path)];
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   627
        let config = Config::load_from_explicit_sources(sources)
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   628
            .expect("expected valid config");
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   629
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   630
        let (_, value) = config.get_inner(b"section", b"item").unwrap();
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   631
        assert_eq!(
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   632
            value,
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   633
            &ConfigValue {
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   634
                bytes: b"value2".to_vec(),
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   635
                line: Some(4)
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   636
            }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   637
        );
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   638
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   639
        let value = config.get(b"section", b"item").unwrap();
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   640
        assert_eq!(value, b"value2",);
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   641
        assert_eq!(
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   642
            config.get_all(b"section", b"item"),
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   643
            [b"value2", b"value1", b"value0"]
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   644
        );
46597
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   645
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   646
        assert_eq!(config.get_u32(b"section2", b"count").unwrap(), Some(4));
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   647
        assert_eq!(
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   648
            config.get_byte_size(b"section2", b"size").unwrap(),
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   649
            Some(1024 + 512)
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   650
        );
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   651
        assert!(config.get_u32(b"section2", b"not-count").is_err());
305d74c262de rust: Add config parsing support for more value types
Simon Sapin <simon.sapin@octobus.net>
parents: 46596
diff changeset
   652
        assert!(config.get_byte_size(b"section2", b"not-size").is_err());
46187
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   653
    }
95d6f31e88db hg-core: add basic config module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   654
}