forked from git/git
-
Notifications
You must be signed in to change notification settings - Fork 142
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
libgit: add higher-level libgit crate
The C functions exported by libgit-sys do not provide an idiomatic Rust interface. To make it easier to use these functions via Rust, add a higher-level "libgit" crate, that wraps the lower-level configset API with an interface that is more Rust-y. This combination of $X and $X-sys crates is a common pattern for FFI in Rust, as documented in "The Cargo Book" [1]. [1] https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages Co-authored-by: Josh Steadmon <[email protected]> Signed-off-by: Josh Steadmon <[email protected]> Signed-off-by: Calvin Wan <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
- Loading branch information
Showing
13 changed files
with
245 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -250,4 +250,5 @@ Release/ | |
/git.VC.db | ||
*.dSYM | ||
/contrib/buildsystems/out | ||
/contrib/libgit-rs/target | ||
/contrib/libgit-sys/target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[package] | ||
name = "libgit" | ||
version = "0.1.0" | ||
edition = "2021" | ||
build = "build.rs" | ||
rust-version = "1.63" # TODO: Once we hit 1.84 or newer, we may want to remove Cargo.lock from | ||
# version control. See https://lore.kernel.org/git/[email protected]/ | ||
|
||
|
||
[lib] | ||
path = "src/lib.rs" | ||
|
||
[dependencies] | ||
libgit-sys = { version = "0.1.0", path = "../libgit-sys" } | ||
|
||
[build-dependencies] | ||
autocfg = "1.4.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# libgit-rs | ||
|
||
Proof-of-concept Git bindings for Rust. | ||
|
||
```toml | ||
[dependencies] | ||
libgit = "0.1.0" | ||
``` | ||
|
||
## Rust version requirements | ||
|
||
libgit-rs should support Rust versions at least as old as the version included | ||
in Debian stable (currently 1.63). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
pub fn main() { | ||
let ac = autocfg::new(); | ||
ac.emit_has_path("std::ffi::c_char"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
use std::ffi::{c_void, CStr, CString}; | ||
use std::path::Path; | ||
|
||
#[cfg(has_std__ffi__c_char)] | ||
use std::ffi::{c_char, c_int}; | ||
|
||
#[cfg(not(has_std__ffi__c_char))] | ||
#[allow(non_camel_case_types)] | ||
type c_char = i8; | ||
|
||
#[cfg(not(has_std__ffi__c_char))] | ||
#[allow(non_camel_case_types)] | ||
type c_int = i32; | ||
|
||
use libgit_sys::*; | ||
|
||
/// A ConfigSet is an in-memory cache for config-like files such as `.gitmodules` or `.gitconfig`. | ||
/// It does not support all config directives; notably, it will not process `include` or | ||
/// `includeIf` directives (but it will store them so that callers can choose whether and how to | ||
/// handle them). | ||
pub struct ConfigSet(*mut libgit_config_set); | ||
impl ConfigSet { | ||
/// Allocate a new ConfigSet | ||
pub fn new() -> Self { | ||
unsafe { ConfigSet(libgit_configset_alloc()) } | ||
} | ||
|
||
/// Load the given files into the ConfigSet; conflicting directives in later files will | ||
/// override those given in earlier files. | ||
pub fn add_files(&mut self, files: &[&Path]) { | ||
for file in files { | ||
let pstr = file.to_str().expect("Invalid UTF-8"); | ||
let rs = CString::new(pstr).expect("Couldn't convert to CString"); | ||
unsafe { | ||
libgit_configset_add_file(self.0, rs.as_ptr()); | ||
} | ||
} | ||
} | ||
|
||
/// Load the value for the given key and attempt to parse it as an i32. Dies with a fatal error | ||
/// if the value cannot be parsed. Returns None if the key is not present. | ||
pub fn get_int(&mut self, key: &str) -> Option<i32> { | ||
let key = CString::new(key).expect("Couldn't convert to CString"); | ||
let mut val: c_int = 0; | ||
unsafe { | ||
if libgit_configset_get_int(self.0, key.as_ptr(), &mut val as *mut c_int) != 0 { | ||
return None; | ||
} | ||
} | ||
|
||
Some(val.into()) | ||
} | ||
|
||
/// Clones the value for the given key. Dies with a fatal error if the value cannot be | ||
/// converted to a String. Returns None if the key is not present. | ||
pub fn get_string(&mut self, key: &str) -> Option<String> { | ||
let key = CString::new(key).expect("Couldn't convert key to CString"); | ||
let mut val: *mut c_char = std::ptr::null_mut(); | ||
unsafe { | ||
if libgit_configset_get_string(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("Couldn't convert val to str")); | ||
free(val as *mut c_void); // Free the xstrdup()ed pointer from the C side | ||
Some(owned_str) | ||
} | ||
} | ||
} | ||
|
||
impl Default for ConfigSet { | ||
fn default() -> Self { | ||
Self::new() | ||
} | ||
} | ||
|
||
impl Drop for ConfigSet { | ||
fn drop(&mut self) { | ||
unsafe { | ||
libgit_configset_free(self.0); | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn load_configs_via_configset() { | ||
let mut cs = ConfigSet::new(); | ||
cs.add_files(&[ | ||
Path::new("testdata/config1"), | ||
Path::new("testdata/config2"), | ||
Path::new("testdata/config3"), | ||
]); | ||
// ConfigSet retrieves correct value | ||
assert_eq!(cs.get_int("trace2.eventTarget"), Some(1)); | ||
// ConfigSet respects last config value set | ||
assert_eq!(cs.get_int("trace2.eventNesting"), Some(3)); | ||
// ConfigSet returns None for missing key | ||
assert_eq!(cs.get_string("foo.bar"), None); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[trace2] | ||
eventNesting = 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[trace2] | ||
eventTarget = 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[trace2] | ||
eventNesting = 3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters