diff --git a/rust-bindings/rust/src/repo.rs b/rust-bindings/rust/src/repo.rs index 827dcb4f..486e087c 100644 --- a/rust-bindings/rust/src/repo.rs +++ b/rust-bindings/rust/src/repo.rs @@ -2,6 +2,7 @@ use crate::RepoListRefsExtFlags; use crate::{Checksum, ObjectName, ObjectType, Repo, RepoTransactionStats}; use ffi; +use ffi::OstreeRepoListObjectsFlags; use glib::ffi as glib_sys; use glib::{self, translate::*, Error, IsA}; use std::{ @@ -23,11 +24,22 @@ unsafe extern "C" fn read_variant_table( set.insert(ObjectName::new_from_variant(value)); } -unsafe fn from_glib_container_variant_set(ptr: *mut glib_sys::GHashTable) -> HashSet { +unsafe extern "C" fn read_variant_table_from_key( + key: glib_sys::gpointer, + _value: glib_sys::gpointer, + hash_set: glib_sys::gpointer, +) { + let key: glib::Variant = from_glib_none(key as *const glib_sys::GVariant); + let set: &mut HashSet = &mut *(hash_set as *mut HashSet); + set.insert(ObjectName::new_from_variant(key)); +} + +unsafe fn from_glib_container_variant_set(ptr: *mut glib_sys::GHashTable, from_key: bool) -> HashSet { let mut set = HashSet::new(); + let read_variant_table_cb = if from_key { read_variant_table_from_key } else { read_variant_table }; glib_sys::g_hash_table_foreach( ptr, - Some(read_variant_table), + Some(read_variant_table_cb), &mut set as *mut HashSet as *mut _, ); glib_sys::g_hash_table_unref(ptr); @@ -115,7 +127,7 @@ impl Repo { &mut error, ); if error.is_null() { - Ok(from_glib_container_variant_set(hashtable)) + Ok(from_glib_container_variant_set(hashtable, false)) } else { Err(from_glib_full(error)) } @@ -147,6 +159,32 @@ impl Repo { } } + /// List all repo objects + pub fn list_objects>( + &self, + flags: OstreeRepoListObjectsFlags, + cancellable: Option<&P>, + ) -> Result, Error> { + unsafe { + let mut error = ptr::null_mut(); + let mut hashtable = ptr::null_mut(); + + ffi::ostree_repo_list_objects( + self.to_glib_none().0, + flags, + &mut hashtable, + cancellable.map(AsRef::as_ref).to_glib_none().0, + &mut error + ); + + if error.is_null() { + Ok(from_glib_container_variant_set(hashtable, true)) + } else { + Err(from_glib_full(error)) + } + } + } + /// List refs with extended options. #[cfg(any(feature = "v2016_4", feature = "dox"))] pub fn list_refs_ext>( diff --git a/rust-bindings/rust/tests/functions/mod.rs b/rust-bindings/rust/tests/functions/mod.rs index 15908731..ae5f99f1 100644 --- a/rust-bindings/rust/tests/functions/mod.rs +++ b/rust-bindings/rust/tests/functions/mod.rs @@ -2,6 +2,34 @@ use crate::util::TestRepo; use gio::NONE_CANCELLABLE; use ostree::{checksum_file_from_input, ObjectType}; +#[test] +fn list_repo_objects() { + let repo = TestRepo::new(); + let commit_checksum = repo.test_commit("test"); + let mut dirtree_cnt = 0; + let mut dirmeta_cnt = 0; + let mut file_cnt = 0; + let mut commit_cnt = 0; + + let objects = repo.repo.list_objects( ffi::OSTREE_REPO_LIST_OBJECTS_ALL, NONE_CANCELLABLE).expect("List Objects"); + for object in objects { + if object.object_type() == ObjectType::Commit { + commit_cnt += 1; + assert_eq!(commit_checksum.to_string(), object.checksum()); + } else if object.object_type() == ObjectType::DirTree { + dirtree_cnt += 1; + } else if object.object_type() == ObjectType::DirMeta { + dirmeta_cnt += 1; + } else if object.object_type() == ObjectType::File { + file_cnt += 1; + } else { panic!("unexpected object type {}", object.object_type()); } + } + assert_eq!(dirtree_cnt, 2); + assert_eq!(dirmeta_cnt, 1); + assert_eq!(file_cnt, 1); + assert_eq!(commit_cnt, 1); +} + #[test] fn should_checksum_file_from_input() { let repo = TestRepo::new();