rust: Bind `ostree_repo_list_commits_starting_with`
authorColin Walters <walters@verbum.org>
Mon, 22 Aug 2022 18:10:16 +0000 (14:10 -0400)
committerColin Walters <walters@verbum.org>
Wed, 24 Aug 2022 13:44:34 +0000 (09:44 -0400)
I wanted to use this as a fallback for
https://github.com/ostreedev/ostree-rs-ext/pull/351/commits/30dee81c22ad5cb90e77198d3ddbcc25d388afb5

rust-bindings/conf/ostree.toml
rust-bindings/src/repo.rs
rust-bindings/tests/repo/mod.rs

index 57c2a7931562eed2d11a0c7f67b2fddbc2b613fc..ec2b594dfa254a27376e1c93482785eabe26c0c0 100644 (file)
@@ -173,6 +173,11 @@ concurrency = "send"
     pattern = "^(load_file)$"
     ignore = true
 
+    [[object.function]]
+    # [MANUAL] hash table with variants
+    pattern = "^(list_commit_objects_starting_with)$"
+    ignore = true
+
 [[object]]
 name = "OSTree.RepoFinder"
 status = "generate"
index 6aeccff55c95b35ed102d9750514dd29e489bf53..1e3e90bcfab933d84b5a3a408d2b726a3668dbfa 100644 (file)
@@ -556,4 +556,52 @@ impl Repo {
         // Safety: We know the variant type will match since we just passed it above
         Ok(crate::DirMetaParsed::from_variant(&v).unwrap())
     }
+
+    /// List all commit objects; an optional prefix filter may be applied.
+    #[doc(alias = "ostree_repo_list_commit_objects_starting_with")]
+    pub fn list_commit_objects_starting_with<P: IsA<gio::Cancellable>>(
+        &self,
+        prefix: Option<&str>,
+        cancellable: Option<&P>,
+    ) -> Result<HashSet<glib::GString>, glib::Error> {
+        use glib::ffi::gpointer;
+        let prefix = prefix.unwrap_or("");
+        unsafe {
+            let repo = self.to_glib_none().0;
+            let mut commits = ptr::null_mut();
+            let cancellable = cancellable.map(|p| p.as_ref()).to_glib_none().0;
+            let mut error = ptr::null_mut();
+            let prefix = prefix.to_glib_none();
+            let r = ffi::ostree_repo_list_commit_objects_starting_with(
+                repo,
+                prefix.0,
+                &mut commits,
+                cancellable,
+                &mut error,
+            );
+            if !error.is_null() {
+                assert_eq!(r, 0);
+                return Err(from_glib_full(error));
+            }
+            assert_ne!(r, 0);
+            let mut ret = HashSet::with_capacity(glib::ffi::g_hash_table_size(commits) as usize);
+            unsafe extern "C" fn visit_hash_table(
+                key: *mut libc::c_void,
+                _value: gpointer,
+                r: *mut libc::c_void,
+            ) -> glib::ffi::gboolean {
+                let key: glib::Variant = from_glib_none(key as *const glib::ffi::GVariant);
+                let checksum = crate::object_name_deserialize(&key).0;
+                let r = &mut *(r as *mut HashSet<glib::GString>);
+                r.insert(checksum);
+                true.into()
+            }
+            glib::ffi::g_hash_table_foreach_remove(
+                commits,
+                Some(visit_hash_table),
+                &mut ret as *mut HashSet<glib::GString> as *mut _,
+            );
+            Ok(ret)
+        }
+    }
 }
index 703dc735866a4236aac0ca28725ed4423d694eab..0a94eb9f7d62e62c880065d680a922a3ea757f21 100644 (file)
@@ -26,6 +26,33 @@ fn should_commit_content_to_repo_and_list_refs_again() {
     assert_eq!(checksum, refs["test"]);
 }
 
+#[test]
+fn list_commits() {
+    let cancellable = gio::NONE_CANCELLABLE;
+    let test_repo = TestRepo::new();
+
+    for prefix in [None, Some("a"), Some("0abcde")] {
+        let commits = test_repo
+            .repo
+            .list_commit_objects_starting_with(prefix, cancellable)
+            .unwrap();
+        assert_eq!(commits.len(), 0);
+    }
+
+    let rev = test_repo.test_commit("testref");
+
+    for prefix in [None, Some(&rev[0..1]), Some(&rev[0..5])] {
+        let commits = test_repo
+            .repo
+            .list_commit_objects_starting_with(prefix, cancellable)
+            .unwrap()
+            .into_iter()
+            .collect::<Vec<_>>();
+        assert_eq!(commits.len(), 1);
+        assert_eq!(commits[0].as_str(), rev.as_str());
+    }
+}
+
 #[test]
 #[cfg(feature = "cap-std-apis")]
 fn cap_std_commit() {