git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 3/3] libgit-rs: add get_ulong() and get_pathname() methods

From
IGionnss via GitGitGadget <gitgitgadget@gmail.com>
Date
Sep 27, 2025, 03:51 UTC
Message-ID
<1ac8d768194b15eaf536000ed5f76f36dd0a39b2.1758945111.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1977.v3.git.1758945111.gitgitgadget@gmail.com>
From: ionnss <zara.leonardo@gmail.com>
Expand the ConfigSet API with additional configuration value types:
- get_ulong(): Parse unsigned long integers for large numeric values
- get_pathname(): Parse file paths, returning PathBuf for type safety

Both functions follow the same pattern as existing get_* methods, using Git's C functions for consistent parsing behavior.

Add comprehensive tests covering normal cases, edge cases, and error handling for all new functionality.

Signed-off-by: ionnss <zara.leonardo@gmail.com>
---
 contrib/libgit-rs/src/config.rs    | 57 ++++++++++++++++++++++++++++--
 contrib/libgit-rs/testdata/config4 |  4 +++
 contrib/libgit-sys/src/lib.rs      | 18 +++++++++-
 3 files changed, 76 insertions(+), 3 deletions(-)
diff --git a/contrib/libgit-rs/src/config.rs b/contrib/libgit-rs/src/config.rs
index 72ee88801b..ffd9f311b6 100644
--- a/contrib/libgit-rs/src/config.rs
+++ b/contrib/libgit-rs/src/config.rs
@@ -1,8 +1,8 @@
 use std::ffi::{c_void, CStr, CString};
-use std::path::Path;
+use std::path::{Path, PathBuf};
 
 #[cfg(has_std__ffi__c_char)]
-use std::ffi::{c_char, c_int};
+use std::ffi::{c_char, c_int, c_ulong};
 
 #[cfg(not(has_std__ffi__c_char))]
 #[allow(non_camel_case_types)]
@@ -12,6 +12,10 @@ type c_char = i8;
 #[allow(non_camel_case_types)]
 type c_int = i32;
 
+#[cfg(not(has_std__ffi__c_char))]
+#[allow(non_camel_case_types)]
+type c_ulong = u64;
+
 use libgit_sys::*;
 
 /// A ConfigSet is an in-memory cache for config-like files such as `.gitmodules` or `.gitconfig`.
@@ -82,6 +86,41 @@ impl ConfigSet {
 
         Some(val != 0)
     }
+
+    /// Load the value for the given key and attempt to parse it as an unsigned long. Dies with a fatal error
+    /// if the value cannot be parsed. Returns None if the key is not present.
+    pub fn get_ulong(&mut self, key: &str) -> Option<u64> {
+        let key = CString::new(key).expect("config key should be valid CString");
+        let mut val: c_ulong = 0;
+        unsafe {
+            if libgit_configset_get_ulong(self.0, key.as_ptr(), &mut val as *mut c_ulong) != 0 {
+                return None;
+            }
+        }
+        Some(val as u64)
+    }
+
+    /// Load the value for the given key and attempt to parse it as a file path. Dies with a fatal error
+    /// if the value cannot be converted to a PathBuf. Returns None if the key is not present.
+    pub fn get_pathname(&mut self, key: &str) -> Option<PathBuf> {
+        let key = CString::new(key).expect("config key should be valid CString");
+        let mut val: *mut c_char = std::ptr::null_mut();
+        unsafe {
+            if libgit_configset_get_pathname(self.0, key.as_ptr(), &mut val as *mut *mut c_char)
+                != 0
+            {
+                return None;
+            }
+            let borrowed_str = CStr::from_ptr(val);
+            let owned_str = String::from(
+                borrowed_str
+                    .to_str()
+                    .expect("config path should be valid UTF-8"),
+            );
+            free(val as *mut c_void); // Free the xstrdup()ed pointer from the C side
+            Some(PathBuf::from(owned_str))
+        }
+    }
 }
 
 impl Default for ConfigSet {
@@ -128,5 +167,19 @@ mod tests {
         assert_eq!(cs.get_bool("test.boolHundred"), Some(true)); // "100" → true
         // Test missing boolean key
         assert_eq!(cs.get_bool("missing.boolean"), None);
+        // Test ulong parsing
+        assert_eq!(cs.get_ulong("test.ulongSmall"), Some(42));
+        assert_eq!(cs.get_ulong("test.ulongBig"), Some(4294967296)); // > 32-bit int
+        assert_eq!(cs.get_ulong("missing.ulong"), None);
+        // Test pathname parsing
+        assert_eq!(
+            cs.get_pathname("test.pathRelative"),
+            Some(PathBuf::from("./some/path"))
+        );
+        assert_eq!(
+            cs.get_pathname("test.pathAbsolute"),
+            Some(PathBuf::from("/usr/bin/git"))
+        );
+        assert_eq!(cs.get_pathname("missing.path"), None);
     }
 }
diff --git a/contrib/libgit-rs/testdata/config4 b/contrib/libgit-rs/testdata/config4
index c0755a32be..bd621ab480 100644
--- a/contrib/libgit-rs/testdata/config4
+++ b/contrib/libgit-rs/testdata/config4
@@ -7,3 +7,7 @@
 	boolZero = 0
 	boolZeroZero = 00
 	boolHundred = 100
+	ulongSmall = 42
+	ulongBig = 4294967296
+	pathRelative = ./some/path
+	pathAbsolute = /usr/bin/git
diff --git a/contrib/libgit-sys/src/lib.rs b/contrib/libgit-sys/src/lib.rs
index b104fda8f6..07386572ec 100644
--- a/contrib/libgit-sys/src/lib.rs
+++ b/contrib/libgit-sys/src/lib.rs
@@ -1,7 +1,7 @@
 use std::ffi::c_void;
 
 #[cfg(has_std__ffi__c_char)]
-use std::ffi::{c_char, c_int};
+use std::ffi::{c_char, c_int, c_ulong};
 
 #[cfg(not(has_std__ffi__c_char))]
 #[allow(non_camel_case_types)]
@@ -11,6 +11,10 @@ pub type c_char = i8;
 #[allow(non_camel_case_types)]
 pub type c_int = i32;
 
+#[cfg(not(has_std__ffi__c_char))]
+#[allow(non_camel_case_types)]
+pub type c_ulong = u64;
+
 extern crate libz_sys;
 
 #[allow(non_camel_case_types)]
@@ -49,6 +53,18 @@ extern "C" {
         dest: *mut c_int,
     ) -> c_int;
 
+    pub fn libgit_configset_get_ulong(
+        cs: *mut libgit_config_set,
+        key: *const c_char,
+        dest: *mut c_ulong,
+    ) -> c_int;
+
+    pub fn libgit_configset_get_pathname(
+        cs: *mut libgit_config_set,
+        key: *const c_char,
+        dest: *mut *mut c_char,
+    ) -> c_int;
+
 }
 
 #[cfg(test)]
-- 
gitgitgadget
Previous: Phillip WoodNext: Phillip Wood
Message 17 of 22 in “libgit-rs: add get_bool() method to ConfigSet”
  1. 0/2 libgit-rs: add get_bool() method to ConfigSetions via GitGitGadget, Sep 25, 2025
  2. 1/2 po: fix escaped underscores in README.mdionnss via GitGitGadget, Sep 25, 2025
  3. 2/2 libgit-rs: add get_bool() method to ConfigSetionnss via GitGitGadget, Sep 25, 2025
  4. Chris TorekSep 26, 2025
  5. Phillip WoodSep 26, 2025
  6. Junio C HamanoSep 26, 2025
  7. 0/3 libgit-rs: add get_bool() method to ConfigSetions via GitGitGadget, Sep 27, 2025
  8. 1/3 po: fix escaped underscores in README.mdionnss via GitGitGadget, Sep 27, 2025
  9. 2/3 libgit-rs: add get_bool() method to ConfigSetionnss via GitGitGadget, Sep 27, 2025
  10. 3/3 libgit-rs: address review feedback for get_bool()ionnss via GitGitGadget, Sep 27, 2025
  11. Junio C HamanoSep 27, 2025
  12. 0/3 libgit-rs: add get_bool() method to ConfigSetions via GitGitGadget, Sep 27, 2025
  13. 1/3 po: fix escaped underscores in README.mdionnss via GitGitGadget, Sep 27, 2025
  14. Phillip WoodSep 29, 2025
  15. 2/3 libgit-rs: add get_bool() method to ConfigSetionnss via GitGitGadget, Sep 27, 2025
  16. Phillip WoodSep 29, 2025
  17. 3/3 libgit-rs: add get_ulong() and get_pathname() methodsionnss via GitGitGadget, Sep 27, 2025
  18. Phillip WoodSep 29, 2025
  19. libgit-rs: add get_bool(), get_ulong(), and get_pathname() methodsions via GitGitGadget, Sep 30, 2025
  20. Phillip WoodOct 1, 2025
  21. brian m. carlsonOct 6, 2025
  22. Phillip WoodOct 8, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.