[gnome-software] rpm-ostree: Implement locally downloaded rpm install
- From: Kalev Lember <klember src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] rpm-ostree: Implement locally downloaded rpm install
- Date: Fri, 25 Jan 2019 12:10:43 +0000 (UTC)
commit c16a317d2b5e0c6e24f6369696746378c35bce23
Author: Kalev Lember <klember redhat com>
Date: Fri Jan 25 13:02:08 2019 +0100
rpm-ostree: Implement locally downloaded rpm install
plugins/rpm-ostree/gs-plugin-rpm-ostree.c | 233 ++++++++++++++++++++++++++++++
1 file changed, 233 insertions(+)
---
diff --git a/plugins/rpm-ostree/gs-plugin-rpm-ostree.c b/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
index 90ce335a..f57de5fe 100644
--- a/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
+++ b/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
@@ -40,6 +40,7 @@
*/
#define GS_RPMOSTREE_CLIENT_ID PACKAGE_NAME
+G_DEFINE_AUTO_CLEANUP_FREE_FUNC(Header, headerFree, NULL)
G_DEFINE_AUTO_CLEANUP_FREE_FUNC(rpmts, rpmtsFree, NULL);
G_DEFINE_AUTO_CLEANUP_FREE_FUNC(rpmdbMatchIterator, rpmdbFreeIterator, NULL);
@@ -462,6 +463,32 @@ make_rpmostree_modifiers_variant (const char *install_package,
}
+ if (install_local_package != NULL) {
+ g_auto(GVariantBuilder) builder;
+ int fd;
+ int idx;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("ah"));
+
+ fd = openat (AT_FDCWD, install_local_package, O_RDONLY | O_CLOEXEC | O_NOCTTY);
+ if (fd == -1) {
+ g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED,
+ "Failed to open %s", install_local_package);
+ return FALSE;
+ }
+
+ idx = g_unix_fd_list_append (fd_list, fd, error);
+ if (idx < 0) {
+ close (fd);
+ return FALSE;
+ }
+
+ g_variant_builder_add (&builder, "h", idx);
+ g_variant_dict_insert_value (&dict, "install-local-packages",
+ g_variant_new ("ah", &builder));
+ close (fd);
+ }
+
*out_fd_list = g_steal_pointer (&fd_list);
*out_modifiers = g_variant_ref_sink (g_variant_dict_end (&dict));
return TRUE;
@@ -762,6 +789,89 @@ gs_plugin_update_app (GsPlugin *plugin,
return TRUE;
}
+gboolean
+gs_plugin_app_install (GsPlugin *plugin,
+ GsApp *app,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GsPluginData *priv = gs_plugin_get_data (plugin);
+ g_autofree gchar *local_filename = NULL;
+ g_autofree gchar *transaction_address = NULL;
+ g_autoptr(GVariant) options = NULL;
+
+ /* only process this app if was created by this plugin */
+ if (g_strcmp0 (gs_app_get_management_plugin (app), gs_plugin_get_name (plugin)) != 0)
+ return TRUE;
+
+ switch (gs_app_get_state (app)) {
+ case AS_APP_STATE_AVAILABLE_LOCAL:
+ if (gs_app_get_local_file (app) == NULL) {
+ g_set_error_literal (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_NOT_SUPPORTED,
+ "local package, but no filename");
+ return FALSE;
+ }
+
+ local_filename = g_file_get_path (gs_app_get_local_file (app));
+ break;
+ default:
+ g_set_error (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_NOT_SUPPORTED,
+ "do not know how to install app in state %s",
+ as_app_state_to_string (gs_app_get_state (app)));
+ return FALSE;
+ }
+
+ gs_app_set_state (app, AS_APP_STATE_INSTALLING);
+
+ options = make_rpmostree_options_variant (FALSE, /* reboot */
+ FALSE, /* allow-downgrade */
+ FALSE, /* cache-only */
+ FALSE, /* download-only */
+ FALSE, /* skip-purge */
+ TRUE, /* no-pull-base */
+ FALSE, /* dry-run */
+ FALSE); /* no-overrides */
+
+ if (!rpmostree_update_deployment (priv->os_proxy,
+ NULL /* install package */,
+ NULL /* remove package */,
+ local_filename,
+ options,
+ &transaction_address,
+ cancellable,
+ error)) {
+ gs_utils_error_convert_gio (error);
+ gs_app_set_state_recover (app);
+ return FALSE;
+ }
+
+ if (!gs_rpmostree_transaction_get_response_sync (priv->sysroot_proxy,
+ transaction_address,
+ cancellable,
+ error)) {
+ gs_utils_error_convert_gio (error);
+ gs_app_set_state_recover (app);
+ return FALSE;
+ }
+
+ /* state is known */
+ gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+
+ /* get the new icon from the package */
+ gs_app_set_local_file (app, NULL);
+ gs_app_add_icon (app, NULL);
+ gs_app_set_pixbuf (app, NULL);
+
+ /* no longer valid */
+ gs_app_clear_source_ids (app);
+
+ return TRUE;
+}
+
gboolean
gs_plugin_app_remove (GsPlugin *plugin,
GsApp *app,
@@ -1029,3 +1139,126 @@ gs_plugin_launch (GsPlugin *plugin,
return gs_plugin_app_launch (plugin, app, error);
}
+
+static void
+add_quirks_from_package_name (GsApp *app, const gchar *package_name)
+{
+ /* these packages don't have a .repo file in their file lists, but
+ * instead install one through rpm scripts / cron job */
+ const gchar *packages_with_repos[] = {
+ "google-chrome-stable",
+ "google-earth-pro-stable",
+ "google-talkplugin",
+ NULL };
+
+ if (g_strv_contains (packages_with_repos, package_name))
+ gs_app_add_quirk (app, GS_APP_QUIRK_HAS_SOURCE);
+}
+
+gboolean
+gs_plugin_file_to_app (GsPlugin *plugin,
+ GsAppList *list,
+ GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ FD_t rpmfd;
+ int r;
+ guint64 epoch;
+ guint64 size;
+ const gchar *name;
+ const gchar *version;
+ const gchar *release;
+ const gchar *license;
+ g_auto(Header) h = NULL;
+ g_auto(rpmts) ts = NULL;
+ g_autofree gchar *evr = NULL;
+ g_autofree gchar *filename = NULL;
+ g_autoptr(GsApp) app = NULL;
+
+ filename = g_file_get_path (file);
+ if (!g_str_has_suffix (filename, ".rpm")) {
+ ret = TRUE;
+ goto out;
+ }
+
+ ts = rpmtsCreate ();
+ rpmtsSetVSFlags (ts, _RPMVSF_NOSIGNATURES);
+
+ /* librpm needs Fopenfd */
+ rpmfd = Fopen (filename, "r.fdio");
+ if (rpmfd == NULL) {
+ g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED,
+ "Opening %s failed", filename);
+ goto out;
+ }
+ if (Ferror (rpmfd)) {
+ g_set_error (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_FAILED,
+ "Opening %s failed: %s",
+ filename,
+ Fstrerror (rpmfd));
+ goto out;
+ }
+
+ if ((r = rpmReadPackageFile (ts, rpmfd, filename, &h)) != RPMRC_OK) {
+ g_set_error (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_FAILED,
+ "Verification of %s failed",
+ filename);
+ goto out;
+ }
+
+ app = gs_app_new (NULL);
+ gs_app_set_metadata (app, "GnomeSoftware::Creator", gs_plugin_get_name (plugin));
+ gs_app_set_management_plugin (app, gs_plugin_get_name (plugin));
+ gs_app_set_kind (app, AS_APP_KIND_GENERIC);
+ gs_app_set_bundle_kind (app, AS_BUNDLE_KIND_PACKAGE);
+ gs_app_set_scope (app, AS_APP_SCOPE_SYSTEM);
+ gs_app_set_state (app, AS_APP_STATE_AVAILABLE_LOCAL);
+
+ /* add default source */
+ name = headerGetString (h, RPMTAG_NAME);
+ g_debug ("rpm: setting source to %s", name);
+ gs_app_add_source (app, name);
+
+ /* add version */
+ epoch = headerGetNumber (h, RPMTAG_EPOCH);
+ version = headerGetString (h, RPMTAG_VERSION);
+ release = headerGetString (h, RPMTAG_RELEASE);
+ if (epoch > 0) {
+ evr = g_strdup_printf ("%" G_GUINT64_FORMAT ":%s-%s",
+ epoch, version, release);
+ } else {
+ evr = g_strdup_printf ("%s-%s",
+ version, release);
+ }
+ g_debug ("rpm: setting version to %s", evr);
+ gs_app_set_version (app, evr);
+
+ /* set size */
+ size = headerGetNumber (h, RPMTAG_SIZE);
+ gs_app_set_size_installed (app, size);
+
+ /* set license */
+ license = headerGetString (h, RPMTAG_LICENSE);
+ if (license != NULL) {
+ g_autofree gchar *license_spdx = NULL;
+ license_spdx = as_utils_license_to_spdx (license);
+ gs_app_set_license (app, GS_APP_QUALITY_NORMAL, license_spdx);
+ g_debug ("rpm: setting license to %s", license_spdx);
+ }
+
+ add_quirks_from_package_name (app, name);
+
+ gs_app_list_add (list, app);
+ ret = TRUE;
+
+out:
+ if (rpmfd)
+ (void) Fclose (rpmfd);
+ return ret;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]