1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
//! Bindings to libgit2's git_libgit2_opts function.
use std::ffi::CString;
use std::ptr;
use crate::string_array::StringArray;
use crate::util::Binding;
use crate::{raw, Buf, ConfigLevel, Error, IntoCString};
/// Set the search path for a level of config data. The search path applied to
/// shared attributes and ignore files, too.
///
/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`],
/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`].
///
/// `path` lists directories delimited by `GIT_PATH_LIST_SEPARATOR`.
/// Use magic path `$PATH` to include the old value of the path
/// (if you want to prepend or append, for instance).
///
/// This function is unsafe as it mutates the global state but cannot guarantee
/// thread-safety. It needs to be externally synchronized with calls to access
/// the global state.
pub unsafe fn set_search_path<P>(level: ConfigLevel, path: P) -> Result<(), Error>
where
P: IntoCString,
{
crate::init();
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int,
level as libc::c_int,
path.into_c_string()?.as_ptr()
));
Ok(())
}
/// Reset the search path for a given level of config data to the default
/// (generally based on environment variables).
///
/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`],
/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`].
///
/// This function is unsafe as it mutates the global state but cannot guarantee
/// thread-safety. It needs to be externally synchronized with calls to access
/// the global state.
pub unsafe fn reset_search_path(level: ConfigLevel) -> Result<(), Error> {
crate::init();
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int,
level as libc::c_int,
core::ptr::null::<u8>()
));
Ok(())
}
/// Get the search path for a given level of config data.
///
/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`],
/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`].
///
/// This function is unsafe as it mutates the global state but cannot guarantee
/// thread-safety. It needs to be externally synchronized with calls to access
/// the global state.
pub unsafe fn get_search_path(level: ConfigLevel) -> Result<CString, Error> {
crate::init();
let buf = Buf::new();
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_GET_SEARCH_PATH as libc::c_int,
level as libc::c_int,
buf.raw() as *const _
));
buf.into_c_string()
}
/// Controls whether or not libgit2 will cache loaded objects. Enabled by
/// default, but disabling this can improve performance and memory usage if
/// loading a large number of objects that will not be referenced again.
/// Disabling this will cause repository objects to clear their caches when next
/// accessed.
pub fn enable_caching(enabled: bool) {
crate::init();
let error = unsafe {
raw::git_libgit2_opts(
raw::GIT_OPT_ENABLE_CACHING as libc::c_int,
enabled as libc::c_int,
)
};
// This function cannot actually fail, but the function has an error return
// for other options that can.
debug_assert!(error >= 0);
}
/// Controls whether or not libgit2 will verify when writing an object that all
/// objects it references are valid. Enabled by default, but disabling this can
/// significantly improve performance, at the cost of potentially allowing the
/// creation of objects that reference invalid objects (due to programming
/// error or repository corruption).
pub fn strict_object_creation(enabled: bool) {
crate::init();
let error = unsafe {
raw::git_libgit2_opts(
raw::GIT_OPT_ENABLE_STRICT_OBJECT_CREATION as libc::c_int,
enabled as libc::c_int,
)
};
// This function cannot actually fail, but the function has an error return
// for other options that can.
debug_assert!(error >= 0);
}
/// Controls whether or not libgit2 will verify that objects loaded have the
/// expected hash. Enabled by default, but disabling this can significantly
/// improve performance, at the cost of relying on repository integrity
/// without checking it.
pub fn strict_hash_verification(enabled: bool) {
crate::init();
let error = unsafe {
raw::git_libgit2_opts(
raw::GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION as libc::c_int,
enabled as libc::c_int,
)
};
// This function cannot actually fail, but the function has an error return
// for other options that can.
debug_assert!(error >= 0);
}
/// Returns the list of git extensions that are supported. This is the list of
/// built-in extensions supported by libgit2 and custom extensions that have
/// been added with [`set_extensions`]. Extensions that have been negated will
/// not be returned.
///
/// # Safety
///
/// libgit2 stores user extensions in a static variable.
/// This function is effectively reading a `static mut` and should be treated as such
pub unsafe fn get_extensions() -> Result<StringArray, Error> {
crate::init();
let mut extensions = raw::git_strarray {
strings: ptr::null_mut(),
count: 0,
};
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_GET_EXTENSIONS as libc::c_int,
&mut extensions
));
Ok(StringArray::from_raw(extensions))
}
/// Set that the given git extensions are supported by the caller. Extensions
/// supported by libgit2 may be negated by prefixing them with a `!`.
/// For example: setting extensions to `[ "!noop", "newext" ]` indicates that
/// the caller does not want to support repositories with the `noop` extension
/// but does want to support repositories with the `newext` extension.
///
/// # Safety
///
/// libgit2 stores user extensions in a static variable.
/// This function is effectively modifying a `static mut` and should be treated as such
pub unsafe fn set_extensions<E>(extensions: &[E]) -> Result<(), Error>
where
for<'x> &'x E: IntoCString,
{
crate::init();
let extensions = extensions
.iter()
.map(|e| e.into_c_string())
.collect::<Result<Vec<_>, _>>()?;
let extension_ptrs = extensions.iter().map(|e| e.as_ptr()).collect::<Vec<_>>();
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_SET_EXTENSIONS as libc::c_int,
extension_ptrs.as_ptr(),
extension_ptrs.len() as libc::size_t
));
Ok(())
}
/// Set whether or not to verify ownership before performing a repository.
/// Enabled by default, but disabling this can lead to code execution vulnerabilities.
pub unsafe fn set_verify_owner_validation(enabled: bool) -> Result<(), Error> {
crate::init();
let error = raw::git_libgit2_opts(
raw::GIT_OPT_SET_OWNER_VALIDATION as libc::c_int,
enabled as libc::c_int,
);
// This function cannot actually fail, but the function has an error return
// for other options that can.
debug_assert!(error >= 0);
Ok(())
}
/// Set the SSL certificate-authority location to `file`. `file` is the location
/// of a file containing several certificates concatenated together.
pub unsafe fn set_ssl_cert_file<P>(file: P) -> Result<(), Error>
where
P: IntoCString,
{
crate::init();
unsafe {
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_SET_SSL_CERT_LOCATIONS as libc::c_int,
file.into_c_string()?.as_ptr(),
core::ptr::null::<libc::c_char>()
));
}
Ok(())
}
/// Set the SSL certificate-authority location to `path`. `path` is the location
/// of a directory holding several certificates, one per file.
pub unsafe fn set_ssl_cert_dir<P>(path: P) -> Result<(), Error>
where
P: IntoCString,
{
crate::init();
unsafe {
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_SET_SSL_CERT_LOCATIONS as libc::c_int,
core::ptr::null::<libc::c_char>(),
path.into_c_string()?.as_ptr()
));
}
Ok(())
}
/// Get the maximum mmap window size
///
/// # Safety
/// This function is reading a C global without synchronization, so it is not
/// thread safe, and should only be called before any thread is spawned.
pub unsafe fn get_mwindow_size() -> Result<libc::size_t, Error> {
crate::init();
let mut size = 0;
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_GET_MWINDOW_SIZE as libc::c_int,
&mut size
));
Ok(size)
}
/// Set the maximum mmap window size
///
/// # Safety
/// This function is modifying a C global without synchronization, so it is not
/// thread safe, and should only be called before any thread is spawned.
pub unsafe fn set_mwindow_size(size: libc::size_t) -> Result<(), Error> {
crate::init();
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_SET_MWINDOW_SIZE as libc::c_int,
size
));
Ok(())
}
/// Get the maximum memory that will be mapped in total by the library
///
/// # Safety
/// This function is reading a C global without synchronization, so it is not
/// thread safe, and should only be called before any thread is spawned.
pub unsafe fn get_mwindow_mapped_limit() -> Result<libc::size_t, Error> {
crate::init();
let mut limit = 0;
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_GET_MWINDOW_MAPPED_LIMIT as libc::c_int,
&mut limit
));
Ok(limit)
}
/// Set the maximum amount of memory that can be mapped at any time
/// by the library.
///
/// # Safety
/// This function is modifying a C global without synchronization, so it is not
/// thread safe, and should only be called before any thread is spawned.
pub unsafe fn set_mwindow_mapped_limit(limit: libc::size_t) -> Result<(), Error> {
crate::init();
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_SET_MWINDOW_MAPPED_LIMIT as libc::c_int,
limit
));
Ok(())
}
/// Get the maximum number of files that will be mapped at any time by the
/// library.
///
/// # Safety
/// This function is reading a C global without synchronization, so it is not
/// thread safe, and should only be called before any thread is spawned.
pub unsafe fn get_mwindow_file_limit() -> Result<libc::size_t, Error> {
crate::init();
let mut limit = 0;
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_GET_MWINDOW_FILE_LIMIT as libc::c_int,
&mut limit
));
Ok(limit)
}
/// Set the maximum number of files that can be mapped at any time
/// by the library. The default (0) is unlimited.
///
/// # Safety
/// This function is modifying a C global without synchronization, so it is not
/// thread safe, and should only be called before any thread is spawned.
pub unsafe fn set_mwindow_file_limit(limit: libc::size_t) -> Result<(), Error> {
crate::init();
try_call!(raw::git_libgit2_opts(
raw::GIT_OPT_SET_MWINDOW_FILE_LIMIT as libc::c_int,
limit
));
Ok(())
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn smoke() {
strict_hash_verification(false);
}
#[test]
fn mwindow_size() {
unsafe {
assert!(set_mwindow_size(1024).is_ok());
assert!(get_mwindow_size().unwrap() == 1024);
}
}
#[test]
fn mwindow_mapped_limit() {
unsafe {
assert!(set_mwindow_mapped_limit(1024).is_ok());
assert!(get_mwindow_mapped_limit().unwrap() == 1024);
}
}
#[test]
fn mwindow_file_limit() {
unsafe {
assert!(set_mwindow_file_limit(1024).is_ok());
assert!(get_mwindow_file_limit().unwrap() == 1024);
}
}
}