changeset 50803:8ff187fbbfea

rust-config: add config getters that don't fall back to defaults This is useful in cases where we access config items that are more... lenient with their types than a fresh new system would allow. For now there is only a single use of this, but we might get more later.
author Raphaël Gomès <rgomes@octobus.net>
date Mon, 13 Feb 2023 18:11:48 +0100
parents f8412da86d05
children 7f8f6fe13fa9
files rust/hg-core/src/config/mod.rs rust/rhg/src/main.rs
diffstat 2 files changed, 84 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/rust/hg-core/src/config/mod.rs	Thu Jul 06 14:32:07 2023 +0200
+++ b/rust/hg-core/src/config/mod.rs	Mon Feb 13 18:11:48 2023 +0100
@@ -360,21 +360,21 @@
         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))
-        }
+    /// 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,
@@ -382,6 +382,7 @@
         item: &[u8],
         expected_type: &'static str,
         parse: impl Fn(&'config [u8]) -> Option<T>,
+        fallback_to_default: bool,
     ) -> Result<Option<T>, HgError>
     where
         Option<T>: TryFrom<&'config DefaultConfigItem, Error = HgError>,
@@ -399,12 +400,15 @@
                 })
                 .into()),
             },
-            None => match self.get_default(section, item)? {
-                Some(default) => Ok(default.try_into()?),
-                None => {
-                    Ok(None)
+            None => {
+                if !fallback_to_default {
+                    return Ok(None);
                 }
-            },
+                match self.get_default(section, item)? {
+                    Some(default) => Ok(default.try_into()?),
+                    None => Ok(None),
+                }
+            }
         }
     }
 
@@ -415,9 +419,29 @@
         section: &[u8],
         item: &[u8],
     ) -> Result<Option<&str>, HgError> {
-        self.get_parse(section, item, "ASCII or UTF-8 string", |value| {
-            str::from_utf8(value).ok()
-        })
+        self.get_parse(
+            section,
+            item,
+            "ASCII or UTF-8 string",
+            |value| str::from_utf8(value).ok(),
+            true,
+        )
+    }
+
+    /// Same as `get_str`, but doesn't fall back to the default `configitem`
+    /// if not defined in the user config.
+    pub fn get_str_no_default(
+        &self,
+        section: &[u8],
+        item: &[u8],
+    ) -> Result<Option<&str>, HgError> {
+        self.get_parse(
+            section,
+            item,
+            "ASCII or UTF-8 string",
+            |value| str::from_utf8(value).ok(),
+            false,
+        )
     }
 
     /// Returns an `Err` if the first value found is not a valid unsigned
@@ -427,9 +451,13 @@
         section: &[u8],
         item: &[u8],
     ) -> Result<Option<u32>, HgError> {
-        self.get_parse(section, item, "valid integer", |value| {
-            str::from_utf8(value).ok()?.parse().ok()
-        })
+        self.get_parse(
+            section,
+            item,
+            "valid integer",
+            |value| str::from_utf8(value).ok()?.parse().ok(),
+            true,
+        )
     }
 
     /// Returns an `Err` if the first value found is not a valid file size
@@ -440,7 +468,13 @@
         section: &[u8],
         item: &[u8],
     ) -> Result<Option<u64>, HgError> {
-        self.get_parse(section, item, "byte quantity", values::parse_byte_size)
+        self.get_parse(
+            section,
+            item,
+            "byte quantity",
+            values::parse_byte_size,
+            true,
+        )
     }
 
     /// Returns an `Err` if the first value found is not a valid boolean.
@@ -451,7 +485,17 @@
         section: &[u8],
         item: &[u8],
     ) -> Result<Option<bool>, HgError> {
-        self.get_parse(section, item, "boolean", values::parse_bool)
+        self.get_parse(section, item, "boolean", values::parse_bool, true)
+    }
+
+    /// Same as `get_option`, but doesn't fall back to the default `configitem`
+    /// if not defined in the user config.
+    pub fn get_option_no_default(
+        &self,
+        section: &[u8],
+        item: &[u8],
+    ) -> Result<Option<bool>, HgError> {
+        self.get_parse(section, item, "boolean", values::parse_bool, false)
     }
 
     /// Returns the corresponding boolean in the config. Returns `Ok(false)`
@@ -464,6 +508,16 @@
         Ok(self.get_option(section, item)?.unwrap_or(false))
     }
 
+    /// Same as `get_bool`, but doesn't fall back to the default `configitem`
+    /// if not defined in the user config.
+    pub fn get_bool_no_default(
+        &self,
+        section: &[u8],
+        item: &[u8],
+    ) -> Result<bool, HgError> {
+        Ok(self.get_option_no_default(section, item)?.unwrap_or(false))
+    }
+
     /// Returns `true` if the extension is enabled, `false` otherwise
     pub fn is_extension_enabled(&self, extension: &[u8]) -> bool {
         let value = self.get(b"extensions", extension);
--- a/rust/rhg/src/main.rs	Thu Jul 06 14:32:07 2023 +0200
+++ b/rust/rhg/src/main.rs	Mon Feb 13 18:11:48 2023 +0100
@@ -86,7 +86,8 @@
         // Mercurial allows users to define generic hooks for commands,
         // fallback if any are detected
         let item = format!("{}-{}", prefix, subcommand_name);
-        let hook_for_command = config.get_str(b"hooks", item.as_bytes())?;
+        let hook_for_command =
+            config.get_str_no_default(b"hooks", item.as_bytes())?;
         if hook_for_command.is_some() {
             let msg = format!("{}-{} hook defined", prefix, subcommand_name);
             return Err(CommandError::unsupported(msg));