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
//! 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(())
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn smoke() {
strict_hash_verification(false);
}
}