diff --git a/git-odb/src/store_impls/dynamic/find.rs b/git-odb/src/store_impls/dynamic/find.rs index 960cdfe6f0..f00ca952c4 100644 --- a/git-odb/src/store_impls/dynamic/find.rs +++ b/git-odb/src/store_impls/dynamic/find.rs @@ -96,6 +96,25 @@ impl super::Handle where S: Deref + Clone, { + /// Return the exact number of packed objects after loading all currently available indices + /// as last seen on disk. + pub fn packed_object_count(&self) -> Result { + let mut count = self.packed_object_count.borrow_mut(); + match *count { + Some(count) => Ok(count), + None => { + let mut snapshot = self.snapshot.borrow_mut(); + *snapshot = self.store.load_all_indices()?; + let mut obj_count = 0; + for index in &snapshot.indices { + obj_count += index.num_objects() as u64; + } + *count = Some(obj_count); + Ok(obj_count) + } + } + } + /// Given a prefix `candidate` with an object id and an initial `hex_len`, check if it only matches a single /// object within the entire object database and increment its `hex_len` by one until it is unambiguous. pub fn disambiguate_prefix(&self, mut candidate: PotentialPrefix) -> Result, Error> { @@ -215,6 +234,7 @@ where match self.store.load_one_index(self.refresh, snapshot.marker)? { Some(new_snapshot) => { *snapshot = new_snapshot; + self.clear_cache(); continue 'outer; } None => { @@ -359,11 +379,16 @@ where match self.store.load_one_index(self.refresh, snapshot.marker)? { Some(new_snapshot) => { *snapshot = new_snapshot; + self.clear_cache(); } None => return Ok(None), } } } + + fn clear_cache(&self) { + self.packed_object_count.borrow_mut().take(); + } } impl git_pack::Find for super::Handle @@ -395,6 +420,7 @@ where match self.store.load_one_index(self.refresh, snapshot.marker) { Ok(Some(new_snapshot)) => { *snapshot = new_snapshot; + self.clear_cache(); } Ok(None) => return false, // nothing more to load, or our refresh mode doesn't allow disk refreshes Err(_) => return false, // something went wrong, nothing we can communicate here with this trait. TODO: Maybe that should change? @@ -445,6 +471,7 @@ where match self.store.load_one_index(self.refresh, snapshot.marker).ok()? { Some(new_snapshot) => { *snapshot = new_snapshot; + self.clear_cache(); continue 'outer; } None => { @@ -481,6 +508,7 @@ where match self.store.load_one_index(self.refresh, snapshot.marker).ok()? { Some(new_snapshot) => { *snapshot = new_snapshot; + self.clear_cache(); } None => return None, } diff --git a/git-odb/src/store_impls/dynamic/handle.rs b/git-odb/src/store_impls/dynamic/handle.rs index 6939b9c8eb..5690b42c41 100644 --- a/git-odb/src/store_impls/dynamic/handle.rs +++ b/git-odb/src/store_impls/dynamic/handle.rs @@ -250,6 +250,7 @@ impl super::Store { token: Some(token), snapshot: RefCell::new(self.collect_snapshot()), max_recursion_depth: Self::INITIAL_MAX_RECURSION_DEPTH, + packed_object_count: Default::default(), } } @@ -265,6 +266,7 @@ impl super::Store { token: Some(token), snapshot: RefCell::new(self.collect_snapshot()), max_recursion_depth: Self::INITIAL_MAX_RECURSION_DEPTH, + packed_object_count: Default::default(), } } @@ -381,6 +383,7 @@ where }, snapshot: RefCell::new(self.store.collect_snapshot()), max_recursion_depth: self.max_recursion_depth, + packed_object_count: Default::default(), } } } diff --git a/git-odb/src/store_impls/dynamic/mod.rs b/git-odb/src/store_impls/dynamic/mod.rs index 1240217be4..50bb93de8b 100644 --- a/git-odb/src/store_impls/dynamic/mod.rs +++ b/git-odb/src/store_impls/dynamic/mod.rs @@ -24,6 +24,7 @@ where pub(crate) token: Option, snapshot: RefCell, + packed_object_count: RefCell>, } /// Decide what happens when all indices are loaded. diff --git a/git-odb/tests/odb/store/dynamic.rs b/git-odb/tests/odb/store/dynamic.rs index f1cad518c7..1e760be9e8 100644 --- a/git-odb/tests/odb/store/dynamic.rs +++ b/git-odb/tests/odb/store/dynamic.rs @@ -463,6 +463,14 @@ fn assert_all_indices_loaded(handle: &git_odb::Handle, num_refreshes: usize, ope ); } +#[test] +fn packed_object_count_causes_all_indices_to_be_loaded() { + let (handle, _tmp) = db_with_all_object_sources().unwrap(); + + assert_eq!(handle.packed_object_count().unwrap(), 139); + assert_all_indices_loaded(&handle, 1, 2); +} + mod disambiguate_prefix { use std::cmp::Ordering;