diff --git a/rpmostree-cxxrs.cxx b/rpmostree-cxxrs.cxx index 6092ec6302..1c50f458a6 100644 --- a/rpmostree-cxxrs.cxx +++ b/rpmostree-cxxrs.cxx @@ -2307,10 +2307,11 @@ extern "C" void (*container_rebuild$) (::rust::Str) = ::rpmostreecxx::container_rebuild; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - container_rebuild$ (treefile); - throw$.ptr = nullptr; - }, + [&] + { + container_rebuild$ (treefile); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3055,11 +3056,12 @@ extern "C" = ::rpmostreecxx::util_next_version; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - new (return$)::rust::String ( - util_next_version$ (auto_version_prefix, version_suffix, last_version)); - throw$.ptr = nullptr; - }, + [&] + { + new (return$)::rust::String ( + util_next_version$ (auto_version_prefix, version_suffix, last_version)); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3088,10 +3090,11 @@ extern "C" = ::rpmostreecxx::rpmostree_main; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - new (return$)::std::int32_t (rpmostree_main$ (args)); - throw$.ptr = nullptr; - }, + [&] + { + new (return$)::std::int32_t (rpmostree_main$ (args)); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3110,10 +3113,11 @@ extern "C" void (*c_unit_tests$) () = ::rpmostreecxx::c_unit_tests; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - c_unit_tests$ (); - throw$.ptr = nullptr; - }, + [&] + { + c_unit_tests$ (); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3124,10 +3128,11 @@ extern "C" void (*client_require_root$) () = ::rpmostreecxx::client_require_root; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - client_require_root$ (); - throw$.ptr = nullptr; - }, + [&] + { + client_require_root$ (); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3140,10 +3145,11 @@ extern "C" = ::rpmostreecxx::new_client_connection; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - new (return$)::rpmostreecxx::ClientConnection *(new_client_connection$ ().release ()); - throw$.ptr = nullptr; - }, + [&] + { + new (return$)::rpmostreecxx::ClientConnection *(new_client_connection$ ().release ()); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3165,10 +3171,11 @@ extern "C" = &::rpmostreecxx::ClientConnection::transaction_connect_progress_sync; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - (self.*transaction_connect_progress_sync$) (address); - throw$.ptr = nullptr; - }, + [&] + { + (self.*transaction_connect_progress_sync$) (address); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3207,11 +3214,12 @@ extern "C" = ::rpmostreecxx::rpmdb_diff; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - new (return$)::rpmostreecxx::RPMDiff *( - rpmdb_diff$ (repo, src, dest, allow_noent).release ()); - throw$.ptr = nullptr; - }, + [&] + { + new (return$)::rpmostreecxx::RPMDiff *( + rpmdb_diff$ (repo, src, dest, allow_noent).release ()); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3265,10 +3273,11 @@ extern "C" = ::rpmostreecxx::nevra_to_cache_branch; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - new (return$)::rust::String (nevra_to_cache_branch$ (nevra)); - throw$.ptr = nullptr; - }, + [&] + { + new (return$)::rust::String (nevra_to_cache_branch$ (nevra)); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3281,10 +3290,11 @@ extern "C" = ::rpmostreecxx::get_repodata_chksum_repr; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - new (return$)::rust::String (get_repodata_chksum_repr$ (pkg)); - throw$.ptr = nullptr; - }, + [&] + { + new (return$)::rust::String (get_repodata_chksum_repr$ (pkg)); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3298,10 +3308,11 @@ extern "C" = ::rpmostreecxx::rpmts_for_commit; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - new (return$)::rpmostreecxx::RpmTs *(rpmts_for_commit$ (repo, rev).release ()); - throw$.ptr = nullptr; - }, + [&] + { + new (return$)::rpmostreecxx::RpmTs *(rpmts_for_commit$ (repo, rev).release ()); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3314,11 +3325,12 @@ extern "C" = ::rpmostreecxx::rpmdb_package_name_list; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - new (return$)::rust::Vec<::rust::String> ( - rpmdb_package_name_list$ (dfd, ::rust::String (::rust::unsafe_bitcopy, *path))); - throw$.ptr = nullptr; - }, + [&] + { + new (return$)::rust::Vec<::rust::String> ( + rpmdb_package_name_list$ (dfd, ::rust::String (::rust::unsafe_bitcopy, *path))); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3333,10 +3345,12 @@ extern "C" = &::rpmostreecxx::RpmTs::package_meta; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - new (return$)::rpmostreecxx::PackageMeta *((self.*package_meta$) (name, arch).release ()); - throw$.ptr = nullptr; - }, + [&] + { + new (return$)::rpmostreecxx::PackageMeta *( + (self.*package_meta$) (name, arch).release ()); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3382,10 +3396,11 @@ extern "C" = &::rpmostreecxx::PackageMeta::provided_paths; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - new (return$)::rust::Vec<::rust::String> ((self.*provided_paths$) ()); - throw$.ptr = nullptr; - }, + [&] + { + new (return$)::rust::Vec<::rust::String> ((self.*provided_paths$) ()); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } @@ -3400,11 +3415,12 @@ extern "C" = ::rpmostreecxx::package_variant_list_for_commit; ::rust::repr::PtrLen throw$; ::rust::behavior::trycatch ( - [&] { - new (return$)::rpmostreecxx::GVariant *( - package_variant_list_for_commit$ (repo, rev, cancellable)); - throw$.ptr = nullptr; - }, + [&] + { + new (return$)::rpmostreecxx::GVariant *( + package_variant_list_for_commit$ (repo, rev, cancellable)); + throw$.ptr = nullptr; + }, ::rust::detail::Fail (throw$)); return throw$; } diff --git a/rust/cxx.h b/rust/cxx.h index 12b5f3baf2..e3e409ea0c 100644 --- a/rust/cxx.h +++ b/rust/cxx.h @@ -20,6 +20,14 @@ #include #endif +#if __cplusplus >= 201703L +#include +#endif + +#if __cplusplus >= 202002L +#include +#endif + namespace rust { inline namespace cxxbridge1 @@ -48,6 +56,10 @@ class String final String (const char *, std::size_t); String (const char16_t *); String (const char16_t *, std::size_t); +#ifdef __cpp_char8_t + String (const char8_t *s); + String (const char8_t *s, std::size_t len); +#endif // Replace invalid Unicode data with the replacement character (U+FFFD). static String lossy (const std::string &) noexcept; @@ -124,6 +136,9 @@ class Str final Str &operator= (const Str &) & noexcept = default; explicit operator std::string () const; +#if __cplusplus >= 201703L + explicit operator std::string_view () const; +#endif // Note: no null terminator. const char *data () const noexcept; @@ -186,6 +201,8 @@ class Slice final : private detail::copy_assignable_if::value> Slice () noexcept; Slice (T *, std::size_t count) noexcept; + template explicit Slice (C &c) : Slice (c.data (), c.size ()) {} + Slice &operator= (const Slice &) & noexcept = default; Slice &operator= (Slice &&) & noexcept = default; @@ -220,10 +237,19 @@ class Slice final : private detail::copy_assignable_if::value> std::array repr; }; +#ifdef __cpp_deduction_guides +template +explicit Slice (C &c) -> Slice ().data ())>>; +#endif // __cpp_deduction_guides + template class Slice::iterator final { public: +#if __cplusplus >= 202002L + using iterator_category = std::contiguous_iterator_tag; +#else using iterator_category = std::random_access_iterator_tag; +#endif using value_type = T; using difference_type = std::ptrdiff_t; using pointer = typename std::add_pointer::type; @@ -241,6 +267,11 @@ template class Slice::iterator final iterator &operator+= (difference_type) noexcept; iterator &operator-= (difference_type) noexcept; iterator operator+ (difference_type) const noexcept; + friend inline iterator + operator+ (difference_type lhs, iterator rhs) noexcept + { + return rhs + lhs; + } iterator operator- (difference_type) const noexcept; difference_type operator- (const iterator &) const noexcept; @@ -256,6 +287,12 @@ template class Slice::iterator final void *pos; std::size_t stride; }; + +#if __cplusplus >= 202002L +static_assert (std::ranges::contiguous_range>); +static_assert (std::contiguous_iterator::iterator>); +#endif + #endif // CXXBRIDGE1_RUST_SLICE #ifndef CXXBRIDGE1_RUST_BOX @@ -700,7 +737,7 @@ typename Slice::iterator::difference_type Slice::iterator::operator- (const iterator &other) const noexcept { auto diff = std::distance (static_cast (other.pos), static_cast (this->pos)); - return diff / this->stride; + return diff / static_cast::iterator::difference_type> (this->stride); } template diff --git a/src/app/rpmostree-db-builtin-diff.cxx b/src/app/rpmostree-db-builtin-diff.cxx index f1384b4ce9..69779320b2 100644 --- a/src/app/rpmostree-db-builtin-diff.cxx +++ b/src/app/rpmostree-db-builtin-diff.cxx @@ -24,6 +24,7 @@ #include #include +#include "rpmostree-clientlib.h" #include "rpmostree-db-builtins.h" #include "rpmostree-libbuiltin.h" #include "rpmostree-package-variants.h" @@ -34,6 +35,7 @@ static char *opt_format; static gboolean opt_changelogs; static char *opt_sysroot; static gboolean opt_base; +static gboolean opt_avail; static gboolean opt_advisories; static GOptionEntry option_entries[] = { @@ -45,6 +47,8 @@ static GOptionEntry option_entries[] = { { "base", 0, 0, G_OPTION_ARG_NONE, &opt_base, "Diff against deployments' base, not layered commits", NULL }, { "advisories", 'a', 0, G_OPTION_ARG_NONE, &opt_advisories, "Also output new advisories", NULL }, + { "avail", 0, 0, G_OPTION_ARG_NONE, &opt_avail, "Diff against the latest available update", + NULL }, { NULL } }; @@ -142,6 +146,26 @@ print_deployment_diff (OstreeRepo *repo, const char *from_desc, OstreeDeployment return print_diff (repo, from_desc, from_checksum, to_desc, to_checksum, cancellable, error); } +static gboolean +load_booted_deployment (const char *sysroot_path, OstreeSysroot **out_sysroot, + OstreeDeployment **out_booted, GCancellable *cancellable, GError **error) +{ + g_autoptr (GFile) sysroot_file = g_file_new_for_path (sysroot_path); + g_autoptr (OstreeSysroot) sysroot = ostree_sysroot_new (sysroot_file); + if (!ostree_sysroot_load (sysroot, cancellable, error)) + return FALSE; + + OstreeDeployment *booted = ostree_sysroot_get_booted_deployment (sysroot); + if (!booted) + return glnx_throw (error, "Not booted into any deployment"); + + if (out_sysroot) + *out_sysroot = (OstreeSysroot *)g_steal_pointer (&sysroot); + if (out_booted) + *out_booted = booted; + return TRUE; +} + gboolean rpmostree_db_builtin_diff (int argc, char **argv, RpmOstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error) @@ -189,18 +213,66 @@ rpmostree_db_builtin_diff (int argc, char **argv, RpmOstreeCommandInvocation *in const char *to_desc = NULL; g_autofree char *to_checksum = NULL; - if (argc < 3) + if (opt_avail) { - /* find booted deployment */ + g_auto (GVariantDict) dict; + if (argc > 1) + { + rpmostree_usage_error (context, "--avail takes at most 1 argument (FROM_REV)", error); + return FALSE; + } + const char *sysroot_path = opt_sysroot ?: "/"; - g_autoptr (GFile) sysroot_file = g_file_new_for_path (sysroot_path); - g_autoptr (OstreeSysroot) sysroot = ostree_sysroot_new (sysroot_file); - if (!ostree_sysroot_load (sysroot, cancellable, error)) + glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL; + if (!rpmostree_load_sysroot (sysroot_path, cancellable, &sysroot_proxy, error)) + return FALSE; + + glnx_unref_object RPMOSTreeOS *os_proxy = NULL; + if (!rpmostree_load_os_proxy (sysroot_proxy, NULL, cancellable, &os_proxy, error)) return FALSE; - OstreeDeployment *booted = ostree_sysroot_get_booted_deployment (sysroot); - if (!booted) - return glnx_throw (error, "Not booted into any deployment"); + if (!rpmostree_os_get_has_cached_update_rpm_diff (os_proxy)) + { + return glnx_throw ( + error, "No available update found; try running `rpm-ostree upgrade --check` first"); + } + + g_autoptr (GVariant) cached_update = rpmostree_os_dup_cached_update (os_proxy); + g_variant_dict_init (&dict, cached_update); + const char *avail_checksum = NULL; + if (!g_variant_dict_lookup (&dict, "checksum", "&s", &avail_checksum)) + { + return glnx_throw (error, "Available update missing checksum"); + } + to_checksum = g_strdup (avail_checksum); + to_desc = "available update"; + + if (argc < 1) + { + g_autoptr (OstreeSysroot) sysroot = NULL; + OstreeDeployment *booted = NULL; + if (!load_booted_deployment (sysroot_path, &sysroot, &booted, cancellable, error)) + return FALSE; + + from_desc = "booted deployment"; + if (!get_checksum_from_deployment (repo, booted, &from_checksum, error)) + return FALSE; + } + else + { + from_desc = argv[0]; + if (!ostree_repo_resolve_rev (repo, from_desc, FALSE, &from_checksum, error)) + return FALSE; + } + } + else if (argc < 3) + { + /* find booted deployment */ + const char *sysroot_path = opt_sysroot ?: "/"; + g_autoptr (OstreeSysroot) sysroot = NULL; + OstreeDeployment *booted = NULL; + if (!load_booted_deployment (sysroot_path, &sysroot, &booted, cancellable, error)) + return FALSE; if (argc < 2) {