Skip to content

Commit ccb48dd

Browse files
committed
fix: thread-safe get/set search path
1 parent 140aa27 commit ccb48dd

File tree

2 files changed

+55
-28
lines changed

2 files changed

+55
-28
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ bitflags = "1.1.0"
2121
libc = "0.2"
2222
log = "0.4.8"
2323
libgit2-sys = { path = "libgit2-sys", version = "0.12.17" }
24+
once_cell = "1.5"
2425

2526
[target."cfg(all(unix, not(target_os = \"macos\")))".dependencies]
2627
openssl-sys = { version = "0.9.0", optional = true }

src/opts.rs

+54-28
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,59 @@
11
//! Bindings to libgit2's git_libgit2_opts function.
22
3+
use std::sync::Mutex;
4+
5+
use once_cell::sync::Lazy;
6+
37
use crate::util::Binding;
48
use crate::{call, raw, Buf, ConfigLevel, Error, IntoCString};
59

10+
static SEARCH_PATH: Lazy<Mutex<SearchPath>> = Lazy::new(|| {
11+
crate::init();
12+
Mutex::new(SearchPath)
13+
});
14+
15+
struct SearchPath;
16+
17+
impl SearchPath {
18+
pub fn set<P>(&self, level: ConfigLevel, path: P) -> Result<(), Error>
19+
where
20+
P: IntoCString,
21+
{
22+
let path = path.into_c_string()?;
23+
unsafe {
24+
call::c_try(raw::git_libgit2_opts(
25+
raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int,
26+
level as libc::c_int,
27+
path.as_ptr(),
28+
))?;
29+
}
30+
Ok(())
31+
}
32+
33+
pub fn reset(&self, level: ConfigLevel) -> Result<(), Error> {
34+
unsafe {
35+
call::c_try(raw::git_libgit2_opts(
36+
raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int,
37+
level as libc::c_int,
38+
core::ptr::null::<u8>(),
39+
))?;
40+
}
41+
Ok(())
42+
}
43+
44+
pub fn get(&self, level: ConfigLevel) -> Result<String, Error> {
45+
let buf = Buf::new();
46+
unsafe {
47+
call::c_try(raw::git_libgit2_opts(
48+
raw::GIT_OPT_GET_SEARCH_PATH as libc::c_int,
49+
level as libc::c_int,
50+
buf.raw(),
51+
))?;
52+
}
53+
Ok(buf.as_str().unwrap().to_string())
54+
}
55+
}
56+
657
/// Set the search path for a level of config data. The search path applied to
758
/// shared attributes and ignore files, too.
859
///
@@ -16,16 +67,7 @@ pub fn set_search_path<P>(level: ConfigLevel, path: P) -> Result<(), Error>
1667
where
1768
P: IntoCString,
1869
{
19-
crate::init();
20-
let path = path.into_c_string()?;
21-
unsafe {
22-
call::c_try(raw::git_libgit2_opts(
23-
raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int,
24-
level as libc::c_int,
25-
path.as_ptr(),
26-
))?;
27-
}
28-
Ok(())
70+
SEARCH_PATH.lock().unwrap().set(level, path)
2971
}
3072

3173
/// Reset the search path for a given level of config data to the default
@@ -34,31 +76,15 @@ where
3476
/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`],
3577
/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`].
3678
pub fn reset_search_path(level: ConfigLevel) -> Result<(), Error> {
37-
crate::init();
38-
unsafe {
39-
call::c_try(raw::git_libgit2_opts(
40-
raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int,
41-
level as libc::c_int,
42-
core::ptr::null::<u8>(),
43-
))?;
44-
}
45-
Ok(())
79+
SEARCH_PATH.lock().unwrap().reset(level)
4680
}
4781

4882
/// Get the search path for a given level of config data.
4983
///
5084
/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`],
5185
/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`].
5286
pub fn get_search_path(level: ConfigLevel) -> Result<String, Error> {
53-
let buf = Buf::new();
54-
unsafe {
55-
call::c_try(raw::git_libgit2_opts(
56-
raw::GIT_OPT_GET_SEARCH_PATH as libc::c_int,
57-
level as libc::c_int,
58-
buf.raw(),
59-
))?;
60-
}
61-
Ok(buf.as_str().unwrap().to_string())
87+
SEARCH_PATH.lock().unwrap().get(level)
6288
}
6389

6490
/// Controls whether or not libgit2 will verify when writing an object that all

0 commit comments

Comments
 (0)