diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 5e943c0d09..87855c85b1 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2953,6 +2953,11 @@ extern "C" { pub fn git_index_entrycount(entry: *const git_index) -> size_t; pub fn git_index_find(at_pos: *mut size_t, index: *mut git_index, path: *const c_char) -> c_int; + pub fn git_index_find_prefix( + at_pos: *mut size_t, + index: *mut git_index, + prefix: *const c_char, + ) -> c_int; pub fn git_index_free(index: *mut git_index); pub fn git_index_get_byindex(index: *mut git_index, n: size_t) -> *const git_index_entry; pub fn git_index_get_bypath( diff --git a/src/index.rs b/src/index.rs index b2e8dfe5c1..f214351891 100644 --- a/src/index.rs +++ b/src/index.rs @@ -596,6 +596,22 @@ impl Index { Ok(Binding::from_raw(&raw as *const _)) } } + + /// Find the first position of any entries matching a prefix. + /// + /// To find the first position of a path inside a given folder, suffix the prefix with a '/'. + pub fn find_prefix(&self, prefix: T) -> Result { + let mut at_pos: size_t = 0; + let entry_path = prefix.into_c_string()?; + unsafe { + try_call!(raw::git_index_find_prefix( + &mut at_pos, + self.raw, + entry_path + )); + Ok(at_pos) + } + } } impl Binding for Index { @@ -746,7 +762,7 @@ mod tests { use std::path::Path; use tempfile::TempDir; - use crate::{Index, IndexEntry, IndexTime, Oid, Repository, ResetType}; + use crate::{ErrorCode, Index, IndexEntry, IndexTime, Oid, Repository, ResetType}; #[test] fn smoke() { @@ -857,6 +873,27 @@ mod tests { assert_eq!(e.path.len(), 6); } + #[test] + fn add_then_find() { + let mut index = Index::new().unwrap(); + let mut e = entry(); + e.path = b"foo/bar".to_vec(); + index.add(&e).unwrap(); + let mut e = entry(); + e.path = b"foo2/bar".to_vec(); + index.add(&e).unwrap(); + assert_eq!(index.get(0).unwrap().path, b"foo/bar"); + assert_eq!( + index.get_path(Path::new("foo/bar"), 0).unwrap().path, + b"foo/bar" + ); + assert_eq!(index.find_prefix(Path::new("foo2/")), Ok(1)); + assert_eq!( + index.find_prefix(Path::new("empty/")).unwrap_err().code(), + ErrorCode::NotFound + ); + } + #[test] fn add_frombuffer_then_read() { let (_td, repo) = crate::test::repo_init();