Wrap a few repo setup and config access functions in libgit-sys. These were selected as proof-of-concept items to show that we can access local config from Rust. Co-authored-by: Josh Steadmon <steadmon@xxxxxxxxxx> Signed-off-by: Calvin Wan <calvinwan@xxxxxxxxxx> Change-Id: I6dd886af8c63e1f0f3251064cd8903aecdf768bb --- .../libgit-sys/public_symbol_export.c | 26 +++++++++ .../libgit-sys/public_symbol_export.h | 8 +++ contrib/libgit-rs/libgit-sys/src/lib.rs | 57 ++++++++++++++++++- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/contrib/libgit-rs/libgit-sys/public_symbol_export.c b/contrib/libgit-rs/libgit-sys/public_symbol_export.c index 39c27d9c1a..65d1620d28 100644 --- a/contrib/libgit-rs/libgit-sys/public_symbol_export.c +++ b/contrib/libgit-rs/libgit-sys/public_symbol_export.c @@ -2,11 +2,37 @@ // original symbols can be hidden. Renaming these with a "libgit_" prefix also // avoid conflicts with other libraries such as libgit2. +#include "git-compat-util.h" #include "contrib/libgit-rs/libgit-sys/public_symbol_export.h" +#include "common-init.h" +#include "config.h" +#include "setup.h" #include "version.h" +extern struct repository *the_repository; + #pragma GCC visibility push(default) +const char *libgit_setup_git_directory(void) +{ + return setup_git_directory(); +} + +int libgit_config_get_int(const char *key, int *dest) +{ + return repo_config_get_int(the_repository, key, dest); +} + +void libgit_init_git(const char **argv) +{ + init_git(argv); +} + +int libgit_parse_maybe_bool(const char *val) +{ + return git_parse_maybe_bool(val); +} + const char *libgit_user_agent(void) { return git_user_agent(); diff --git a/contrib/libgit-rs/libgit-sys/public_symbol_export.h b/contrib/libgit-rs/libgit-sys/public_symbol_export.h index a3372f93fa..64332f30de 100644 --- a/contrib/libgit-rs/libgit-sys/public_symbol_export.h +++ b/contrib/libgit-rs/libgit-sys/public_symbol_export.h @@ -1,6 +1,14 @@ #ifndef PUBLIC_SYMBOL_EXPORT_H #define PUBLIC_SYMBOL_EXPORT_H +const char *libgit_setup_git_directory(void); + +int libgit_config_get_int(const char *key, int *dest); + +void libgit_init_git(const char **argv); + +int libgit_parse_maybe_bool(const char *val); + const char *libgit_user_agent(void); const char *libgit_user_agent_sanitized(void); diff --git a/contrib/libgit-rs/libgit-sys/src/lib.rs b/contrib/libgit-rs/libgit-sys/src/lib.rs index 346b26083d..9b2e85dff8 100644 --- a/contrib/libgit-rs/libgit-sys/src/lib.rs +++ b/contrib/libgit-rs/libgit-sys/src/lib.rs @@ -1,8 +1,19 @@ -use std::ffi::c_char; +use std::ffi::{c_char, c_int}; extern crate libz_sys; extern "C" { + pub fn libgit_setup_git_directory() -> *const c_char; + + // From config.c + pub fn libgit_config_get_int(key: *const c_char, dest: *mut c_int) -> c_int; + + // From common-init.c + pub fn libgit_init_git(argv: *const *const c_char); + + // From parse.c + pub fn libgit_parse_maybe_bool(val: *const c_char) -> c_int; + // From version.c pub fn libgit_user_agent() -> *const c_char; pub fn libgit_user_agent_sanitized() -> *const c_char; @@ -10,7 +21,7 @@ extern "C" { #[cfg(test)] mod tests { - use std::ffi::CStr; + use std::ffi::{CStr, CString}; use super::*; @@ -39,4 +50,46 @@ mod tests { agent ); } + + #[test] + fn parse_bools_from_strings() { + let arg = CString::new("true").unwrap(); + assert_eq!(unsafe { libgit_parse_maybe_bool(arg.as_ptr()) }, 1); + + let arg = CString::new("yes").unwrap(); + assert_eq!(unsafe { libgit_parse_maybe_bool(arg.as_ptr()) }, 1); + + let arg = CString::new("false").unwrap(); + assert_eq!(unsafe { libgit_parse_maybe_bool(arg.as_ptr()) }, 0); + + let arg = CString::new("no").unwrap(); + assert_eq!(unsafe { libgit_parse_maybe_bool(arg.as_ptr()) }, 0); + + let arg = CString::new("maybe").unwrap(); + assert_eq!(unsafe { libgit_parse_maybe_bool(arg.as_ptr()) }, -1); + } + + #[test] + fn access_configs() { + /* + * Since we can't easily set a config for the local repo, test + * for the existence of a key rather than a specific value + */ + let fake_argv = [std::ptr::null::<c_char>()]; + unsafe { + libgit_init_git(fake_argv.as_ptr()); + libgit_setup_git_directory(); + } + let mut dest: c_int = 0; + let key = CString::new("core.repositoryformatversion").unwrap(); + unsafe { + let val = libgit_config_get_int(key.as_ptr(), &mut dest as *mut i32); + assert_eq!(val, 0) + }; + let missing_key = CString::new("foo.bar").unwrap(); + unsafe { + let val = libgit_config_get_int(missing_key.as_ptr(), &mut dest as *mut i32); + assert_eq!(val, 1) + }; + } } -- 2.46.0.469.g59c65b2a67-goog