1
1
//! Bindings to libgit2's git_libgit2_opts function.
2
2
3
3
use std:: ffi:: CString ;
4
- use std:: sync:: Mutex ;
5
-
6
- use once_cell:: sync:: Lazy ;
7
4
8
5
use crate :: util:: Binding ;
9
6
use crate :: { call, raw, Buf , ConfigLevel , Error , IntoCString } ;
10
7
11
- static SEARCH_PATH : Lazy < Mutex < SearchPath > > = Lazy :: new ( || {
12
- crate :: init ( ) ;
13
- Mutex :: new ( SearchPath )
14
- } ) ;
15
-
16
- struct SearchPath ;
17
-
18
- impl SearchPath {
19
- pub fn set < P > ( & self , level : ConfigLevel , path : P ) -> Result < ( ) , Error >
20
- where
21
- P : IntoCString ,
22
- {
23
- let path = path. into_c_string ( ) ?;
24
- unsafe {
25
- call:: c_try ( raw:: git_libgit2_opts (
26
- raw:: GIT_OPT_SET_SEARCH_PATH as libc:: c_int ,
27
- level as libc:: c_int ,
28
- path. as_ptr ( ) ,
29
- ) ) ?;
30
- }
31
- Ok ( ( ) )
32
- }
33
-
34
- pub fn reset ( & self , level : ConfigLevel ) -> Result < ( ) , Error > {
35
- unsafe {
36
- call:: c_try ( raw:: git_libgit2_opts (
37
- raw:: GIT_OPT_SET_SEARCH_PATH as libc:: c_int ,
38
- level as libc:: c_int ,
39
- core:: ptr:: null :: < u8 > ( ) ,
40
- ) ) ?;
41
- }
42
- Ok ( ( ) )
43
- }
44
-
45
- pub fn get ( & self , level : ConfigLevel ) -> Result < CString , Error > {
46
- let buf = Buf :: new ( ) ;
47
- unsafe {
48
- call:: c_try ( raw:: git_libgit2_opts (
49
- raw:: GIT_OPT_GET_SEARCH_PATH as libc:: c_int ,
50
- level as libc:: c_int ,
51
- buf. raw ( ) ,
52
- ) ) ?;
53
- }
54
- buf. into_c_string ( )
55
- }
56
- }
57
-
58
8
/// Set the search path for a level of config data. The search path applied to
59
9
/// shared attributes and ignore files, too.
60
10
///
@@ -64,28 +14,56 @@ impl SearchPath {
64
14
/// `path` lists directories delimited by `GIT_PATH_LIST_SEPARATOR`.
65
15
/// Use magic path `$PATH` to include the old value of the path
66
16
/// (if you want to prepend or append, for instance).
67
- pub fn set_search_path < P > ( level : ConfigLevel , path : P ) -> Result < ( ) , Error >
17
+ ///
18
+ /// This function is unsafe as it mutates the global state but cannot guarantee
19
+ /// thread-safety. It needs to be externally synchronized with calls to access
20
+ /// the global state.
21
+ pub unsafe fn set_search_path < P > ( level : ConfigLevel , path : P ) -> Result < ( ) , Error >
68
22
where
69
23
P : IntoCString ,
70
24
{
71
- SEARCH_PATH . lock ( ) . unwrap ( ) . set ( level, path)
25
+ call:: c_try ( raw:: git_libgit2_opts (
26
+ raw:: GIT_OPT_SET_SEARCH_PATH as libc:: c_int ,
27
+ level as libc:: c_int ,
28
+ path. into_c_string ( ) ?. as_ptr ( ) ,
29
+ ) ) ?;
30
+ Ok ( ( ) )
72
31
}
73
32
74
33
/// Reset the search path for a given level of config data to the default
75
34
/// (generally based on environment variables).
76
35
///
77
36
/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`],
78
37
/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`].
79
- pub fn reset_search_path ( level : ConfigLevel ) -> Result < ( ) , Error > {
80
- SEARCH_PATH . lock ( ) . unwrap ( ) . reset ( level)
38
+ ///
39
+ /// This function is unsafe as it mutates the global state but cannot guarantee
40
+ /// thread-safety. It needs to be externally synchronized with calls to access
41
+ /// the global state.
42
+ pub unsafe fn reset_search_path ( level : ConfigLevel ) -> Result < ( ) , Error > {
43
+ call:: c_try ( raw:: git_libgit2_opts (
44
+ raw:: GIT_OPT_SET_SEARCH_PATH as libc:: c_int ,
45
+ level as libc:: c_int ,
46
+ core:: ptr:: null :: < u8 > ( ) ,
47
+ ) ) ?;
48
+ Ok ( ( ) )
81
49
}
82
50
83
51
/// Get the search path for a given level of config data.
84
52
///
85
53
/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`],
86
54
/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`].
87
- pub fn get_search_path ( level : ConfigLevel ) -> Result < CString , Error > {
88
- SEARCH_PATH . lock ( ) . unwrap ( ) . get ( level)
55
+ ///
56
+ /// This function is unsafe as it mutates the global state but cannot guarantee
57
+ /// thread-safety. It needs to be externally synchronized with calls to access
58
+ /// the global state.
59
+ pub unsafe fn get_search_path ( level : ConfigLevel ) -> Result < CString , Error > {
60
+ let buf = Buf :: new ( ) ;
61
+ call:: c_try ( raw:: git_libgit2_opts (
62
+ raw:: GIT_OPT_GET_SEARCH_PATH as libc:: c_int ,
63
+ level as libc:: c_int ,
64
+ buf. raw ( ) ,
65
+ ) ) ?;
66
+ buf. into_c_string ( )
89
67
}
90
68
91
69
/// Controls whether or not libgit2 will verify when writing an object that all
@@ -134,25 +112,34 @@ mod test {
134
112
#[ test]
135
113
fn search_path ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
136
114
let path = "fake_path" ;
137
- let original = get_search_path ( ConfigLevel :: Global ) ;
115
+ let original = unsafe { get_search_path ( ConfigLevel :: Global ) } ;
138
116
assert_ne ! ( original, Ok ( path. into_c_string( ) ?) ) ;
139
117
140
118
// Set
141
- set_search_path ( ConfigLevel :: Global , & path) ?;
119
+ unsafe {
120
+ set_search_path ( ConfigLevel :: Global , & path) ?;
121
+ }
142
122
assert_eq ! (
143
- get_search_path( ConfigLevel :: Global ) ,
123
+ unsafe { get_search_path( ConfigLevel :: Global ) } ,
144
124
Ok ( path. into_c_string( ) ?)
145
125
) ;
146
126
147
127
// Append
148
128
let paths = join_paths ( [ "$PATH" , path] . iter ( ) ) ?;
149
129
let expected_paths = join_paths ( [ path, path] . iter ( ) ) ?. into_c_string ( ) ?;
150
- set_search_path ( ConfigLevel :: Global , paths) ?;
151
- assert_eq ! ( get_search_path( ConfigLevel :: Global ) , Ok ( expected_paths) ) ;
130
+ unsafe {
131
+ set_search_path ( ConfigLevel :: Global , paths) ?;
132
+ }
133
+ assert_eq ! (
134
+ unsafe { get_search_path( ConfigLevel :: Global ) } ,
135
+ Ok ( expected_paths)
136
+ ) ;
152
137
153
138
// Reset
154
- reset_search_path ( ConfigLevel :: Global ) ?;
155
- assert_eq ! ( get_search_path( ConfigLevel :: Global ) , original) ;
139
+ unsafe {
140
+ reset_search_path ( ConfigLevel :: Global ) ?;
141
+ }
142
+ assert_eq ! ( unsafe { get_search_path( ConfigLevel :: Global ) } , original) ;
156
143
157
144
Ok ( ( ) )
158
145
}
0 commit comments