diff rust/hg-core/src/config/mod.rs @ 50802:f8412da86d05

rust-config: add support for default config items Now that configitems.toml exists, we can read from it the default values for all core config items. We will add the devel-warning for use of undeclared config items in a later patch when we're done adding the missing entries for `rhg`.
author Rapha?l Gom?s <rgomes@octobus.net>
date Thu, 06 Jul 2023 14:32:07 +0200
parents af9d050f2bb8
children 8ff187fbbfea
line wrap: on
line diff
--- a/rust/hg-core/src/config/mod.rs	Mon Jan 23 18:08:11 2023 +0100
+++ b/rust/hg-core/src/config/mod.rs	Thu Jul 06 14:32:07 2023 +0200
@@ -9,14 +9,19 @@
 
 //! Mercurial config parsing and interfaces.
 
+pub mod config_items;
 mod layer;
 mod plain_info;
 mod values;
 pub use layer::{ConfigError, ConfigOrigin, ConfigParseError};
+use lazy_static::lazy_static;
 pub use plain_info::PlainInfo;
 
+use self::config_items::DefaultConfig;
+use self::config_items::DefaultConfigItem;
 use self::layer::ConfigLayer;
 use self::layer::ConfigValue;
+use crate::errors::HgError;
 use crate::errors::{HgResultExt, IoResultExt};
 use crate::utils::files::get_bytes_from_os_str;
 use format_bytes::{write_bytes, DisplayBytes};
@@ -26,6 +31,14 @@
 use std::path::{Path, PathBuf};
 use std::str;
 
+lazy_static! {
+    static ref DEFAULT_CONFIG: Result<DefaultConfig, HgError> = {
+        DefaultConfig::from_contents(include_str!(
+            "../../../../mercurial/configitems.toml"
+        ))
+    };
+}
+
 /// Holds the config values for the current repository
 /// TODO update this docstring once we support more sources
 #[derive(Clone)]
@@ -347,13 +360,32 @@
         self.plain = plain;
     }
 
+        /// Returns the default value for the given config item, if any.
+        pub fn get_default(
+            &self,
+            section: &[u8],
+            item: &[u8],
+        ) -> Result<Option<&DefaultConfigItem>, HgError> {
+            let default_config = DEFAULT_CONFIG.as_ref().map_err(|e| {
+                HgError::abort(
+                    e.to_string(),
+                    crate::exit_codes::ABORT,
+                    Some("`mercurial/configitems.toml` is not valid".into()),
+                )
+            })?;
+            Ok(default_config.get(section, item))
+        }
+
     fn get_parse<'config, T: 'config>(
         &'config self,
         section: &[u8],
         item: &[u8],
         expected_type: &'static str,
         parse: impl Fn(&'config [u8]) -> Option<T>,
-    ) -> Result<Option<T>, ConfigValueParseError> {
+    ) -> Result<Option<T>, HgError>
+    where
+        Option<T>: TryFrom<&'config DefaultConfigItem, Error = HgError>,
+    {
         match self.get_inner(section, item) {
             Some((layer, v)) => match parse(&v.bytes) {
                 Some(b) => Ok(Some(b)),
@@ -364,9 +396,15 @@
                     section: section.to_owned(),
                     item: item.to_owned(),
                     expected_type,
-                })),
+                })
+                .into()),
             },
-            None => Ok(None),
+            None => match self.get_default(section, item)? {
+                Some(default) => Ok(default.try_into()?),
+                None => {
+                    Ok(None)
+                }
+            },
         }
     }
 
@@ -376,7 +414,7 @@
         &self,
         section: &[u8],
         item: &[u8],
-    ) -> Result<Option<&str>, ConfigValueParseError> {
+    ) -> Result<Option<&str>, HgError> {
         self.get_parse(section, item, "ASCII or UTF-8 string", |value| {
             str::from_utf8(value).ok()
         })
@@ -388,7 +426,7 @@
         &self,
         section: &[u8],
         item: &[u8],
-    ) -> Result<Option<u32>, ConfigValueParseError> {
+    ) -> Result<Option<u32>, HgError> {
         self.get_parse(section, item, "valid integer", |value| {
             str::from_utf8(value).ok()?.parse().ok()
         })
@@ -401,7 +439,7 @@
         &self,
         section: &[u8],
         item: &[u8],
-    ) -> Result<Option<u64>, ConfigValueParseError> {
+    ) -> Result<Option<u64>, HgError> {
         self.get_parse(section, item, "byte quantity", values::parse_byte_size)
     }
 
@@ -412,7 +450,7 @@
         &self,
         section: &[u8],
         item: &[u8],
-    ) -> Result<Option<bool>, ConfigValueParseError> {
+    ) -> Result<Option<bool>, HgError> {
         self.get_parse(section, item, "boolean", values::parse_bool)
     }
 
@@ -422,7 +460,7 @@
         &self,
         section: &[u8],
         item: &[u8],
-    ) -> Result<bool, ConfigValueParseError> {
+    ) -> Result<bool, HgError> {
         Ok(self.get_option(section, item)?.unwrap_or(false))
     }