diff --git a/Cargo.lock b/Cargo.lock index a996982b..4bea80bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -676,6 +676,7 @@ dependencies = [ "cmake", "cxx", "cxx-build", + "glib", "system-deps 3.0.0", ] @@ -1236,6 +1237,7 @@ dependencies = [ "gio-sys", "glib", "glib-sys", + "gobject-sys", "indicatif", "lazy_static", "libc", diff --git a/Cargo.toml b/Cargo.toml index 9a0452de..1920d166 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ cxx = "1.0.32" envsubst = "0.2.0" gio = "0.9.1" gio-sys = "0.10.1" +gobject-sys = "0.10.0" glib = "0.10.3" glib-sys = "0.10.1" indicatif = "0.15.0" diff --git a/rust/libdnf-sys/Cargo.toml b/rust/libdnf-sys/Cargo.toml index d011c67d..48566c17 100644 --- a/rust/libdnf-sys/Cargo.toml +++ b/rust/libdnf-sys/Cargo.toml @@ -7,6 +7,7 @@ links = "dnf" [dependencies] cxx = "1.0.32" +glib = "0.10.3" [lib] name = "libdnf_sys" diff --git a/rust/src/cxxrsutil.rs b/rust/src/cxxrsutil.rs index e81ba27e..dcee49d2 100644 --- a/rust/src/cxxrsutil.rs +++ b/rust/src/cxxrsutil.rs @@ -80,7 +80,7 @@ macro_rules! cxxrs_bind { paste! { $( #[repr(transparent)] - pub struct []($sys::[<$ns $i>]); + pub struct [](pub(crate) $sys::[<$ns $i>]); unsafe impl ExternType for [] { type Id = type_id!(rpmostreecxx::[<$ns $i>]); @@ -96,6 +96,7 @@ macro_rules! cxxrs_bind { // This macro is special to ostree types currently. cxxrs_bind!(Ostree, ostree, ostree_sys, [Sysroot, Repo, Deployment]); cxxrs_bind!(G, gio, gio_sys, [Cancellable]); +cxxrs_bind!(G, glib, gobject_sys, [Object]); cxxrs_bind!(G, glib, glib_sys, [VariantDict]); // An error type helper; separate from the GObject bridging diff --git a/rust/src/lib.rs b/rust/src/lib.rs index a117eef1..7c4255bf 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -35,6 +35,7 @@ pub mod ffi { #[allow(dead_code)] type OstreeRepo = crate::FFIOstreeRepo; type OstreeDeployment = crate::FFIOstreeDeployment; + type GObject = crate::FFIGObject; type GCancellable = crate::FFIGCancellable; type GVariantDict = crate::FFIGVariantDict; @@ -258,8 +259,8 @@ pub mod ffi { fn ror_lockfile_read(filenames: &Vec) -> Result>; fn ror_lockfile_write( filename: &str, - packages: Vec, - rpmmd_repos: Vec, + packages: Pin<&mut CxxGObjectArray>, + rpmmd_repos: Pin<&mut CxxGObjectArray>, ) -> Result<()>; } @@ -268,6 +269,13 @@ pub mod ffi { fn cache_branch_to_nevra(nevra: &str) -> String; } + unsafe extern "C++" { + include!("rpmostree-cxxrsutil.hpp"); + type CxxGObjectArray; + fn length(self: Pin<&mut CxxGObjectArray>) -> u32; + fn get(self: Pin<&mut CxxGObjectArray>, i: u32) -> &mut GObject; + } + unsafe extern "C++" { include!("rpmostree-util.h"); // Currently only used in unit tests diff --git a/rust/src/lockfile.rs b/rust/src/lockfile.rs index c9f16ba0..ac4efa1c 100644 --- a/rust/src/lockfile.rs +++ b/rust/src/lockfile.rs @@ -21,6 +21,7 @@ use std::convert::TryInto; use std::io; use std::iter::Extend; use std::path::Path; +use std::pin::Pin; /// Given a lockfile filename, parse it fn lockfile_parse>(filename: P) -> Result { @@ -208,8 +209,8 @@ pub(crate) fn ror_lockfile_read(filenames: &Vec) -> CxxResult, - rpmmd_repos: Vec, + mut packages: Pin<&mut crate::ffi::CxxGObjectArray>, + mut rpmmd_repos: Pin<&mut crate::ffi::CxxGObjectArray>, ) -> CxxResult<()> { // get current time, but scrub nanoseconds; it's overkill to serialize that let now = { @@ -225,8 +226,9 @@ pub(crate) fn ror_lockfile_write( }), }; - for pkg in packages { - let pkg_ref = unsafe { &mut *(pkg as *mut libdnf_sys::DnfPackage) }; + for i in 0..(packages.as_mut().length()) { + let pkg = packages.as_mut().get(i); + let pkg_ref = unsafe { &mut *(&mut pkg.0 as *mut _ as *mut libdnf_sys::DnfPackage) }; let name = dnf_package_get_name(pkg_ref).unwrap(); let evr = dnf_package_get_evr(pkg_ref).unwrap(); let arch = dnf_package_get_arch(pkg_ref).unwrap(); @@ -250,8 +252,9 @@ pub(crate) fn ror_lockfile_write( .as_mut() .unwrap(); - for rpmmd_repo in rpmmd_repos { - let repo_ref = unsafe { &mut *(rpmmd_repo as *mut libdnf_sys::DnfRepo) }; + for i in 0..rpmmd_repos.as_mut().length() { + let repo_ref = rpmmd_repos.as_mut().get(i); + let repo_ref = unsafe { &mut *(&mut repo_ref.0 as *mut _ as *mut libdnf_sys::DnfRepo) }; let id = dnf_repo_get_id(repo_ref).unwrap(); let generated = dnf_repo_get_timestamp_generated(repo_ref).unwrap(); let generated: i64 = match generated.try_into() { diff --git a/src/app/rpmostree-compose-builtin-tree.cxx b/src/app/rpmostree-compose-builtin-tree.cxx index 219f2689..37a99d6a 100644 --- a/src/app/rpmostree-compose-builtin-tree.cxx +++ b/src/app/rpmostree-compose-builtin-tree.cxx @@ -382,12 +382,8 @@ install_packages (RpmOstreeTreeComposeContext *self, g_autoptr(GPtrArray) rpmmd_repos = rpmostree_get_enabled_rpmmd_repos (rpmostree_context_get_dnf (self->corectx), DNF_REPO_ENABLED_PACKAGES); - auto pkgs_v = rust::Vec(); - for (guint i = 0; i < pkgs->len; i++) - pkgs_v.push_back((guint64)pkgs->pdata[i]); - auto repos_v = rust::Vec(); - for (guint i = 0; i < rpmmd_repos->len; i++) - repos_v.push_back((guint64)rpmmd_repos->pdata[i]); + auto pkgs_v = rpmostreecxx::CxxGObjectArray(pkgs); + auto repos_v = rpmostreecxx::CxxGObjectArray(rpmmd_repos); rpmostreecxx::ror_lockfile_write(opt_write_lockfile_to, pkgs_v, repos_v); } diff --git a/src/libpriv/rpmostree-cxxrs-prelude.h b/src/libpriv/rpmostree-cxxrs-prelude.h index 8e0f6367..d20b6adc 100644 --- a/src/libpriv/rpmostree-cxxrs-prelude.h +++ b/src/libpriv/rpmostree-cxxrs-prelude.h @@ -29,6 +29,7 @@ namespace rpmostreecxx { typedef ::OstreeRepo OstreeRepo; typedef ::OstreeDeployment OstreeDeployment; typedef ::GCancellable GCancellable; + typedef ::GObject GObject; typedef ::GVariantDict GVariantDict; } diff --git a/src/libpriv/rpmostree-cxxrsutil.hpp b/src/libpriv/rpmostree-cxxrsutil.hpp new file mode 100644 index 00000000..9110343b --- /dev/null +++ b/src/libpriv/rpmostree-cxxrsutil.hpp @@ -0,0 +1,53 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2 of the licence or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#pragma once + +#include +#include +#include +#include + +#include "rust/cxx.h" + +// Helpers corresponding to cxxrsutil.rs +namespace rpmostreecxx { + +// Wrapper for an array of GObjects. This is a hack until +// cxx-rs gains support for either std::vector<> or Vec +// with nontrivial types. +class CxxGObjectArray final { +public: + CxxGObjectArray(GPtrArray *arr_p) : arr(arr_p) { + g_ptr_array_ref(arr); + }; + ~CxxGObjectArray() { + g_ptr_array_unref(arr); + } + + unsigned int length() { + return (unsigned int)arr->len; + } + + ::GObject& get(unsigned int i) { + g_assert_cmpuint(i, <, arr->len); + return *(::GObject*)arr->pdata[i]; + } + GPtrArray* arr; +}; + +} // namespace