/** * gs_plugin_xdg_app_create_installed: */ static GsApp * gs_plugin_xdg_app_create_installed (GsPlugin *plugin, XdgAppInstalledRef *xref, GError **error) { g_autofree gchar *id = NULL; g_autoptr(AsIcon) icon = NULL; g_autoptr(GsApp) app = NULL; g_return_val_if_fail (xref != NULL, NULL); /* * Only show the current application in GNOME Software * * You can have multiple versions/branches of a particular app-id * installed but only one of them is "current" where this means: * 1) the default to launch unless you specify a version * 2) The one that gets its exported files exported */ if (!xdg_app_installed_ref_get_is_current (xref) && xdg_app_ref_get_kind (XDG_APP_REF(xref)) == XDG_APP_REF_KIND_APP) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_NOT_SUPPORTED, "%s not current, ignoring", xdg_app_ref_get_name (XDG_APP_REF (xref))); return NULL; } /* create new object */ id = gs_plugin_xdg_app_build_id (XDG_APP_REF (xref)); app = gs_app_new (id); gs_plugin_xdg_app_set_metadata_installed (app, xref); switch (xdg_app_ref_get_kind (XDG_APP_REF(xref))) { case XDG_APP_REF_KIND_APP: gs_app_set_kind (app, AS_APP_KIND_DESKTOP); break; case XDG_APP_REF_KIND_RUNTIME: gs_app_set_xdgapp_kind (app, XDG_APP_REF_KIND_RUNTIME); gs_app_set_kind (app, AS_APP_KIND_RUNTIME); gs_app_set_name (app, GS_APP_QUALITY_NORMAL, xdg_app_ref_get_name (XDG_APP_REF (xref))); gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Framework for applications"); gs_app_set_version (app, xdg_app_ref_get_branch (XDG_APP_REF (xref))); icon = as_icon_new (); as_icon_set_kind (icon, AS_ICON_KIND_STOCK); as_icon_set_name (icon, "system-run-symbolic"); gs_app_set_icon (app, icon); break; default: g_set_error_literal (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_NOT_SUPPORTED, "XdgAppRefKind not known"); return NULL; } return g_object_ref (app); }
/** * gs_plugin_xdg_app_build_id: */ static gchar * gs_plugin_xdg_app_build_id (XdgAppRef *xref) { if (xdg_app_ref_get_kind (xref) == XDG_APP_REF_KIND_APP) return g_strdup_printf ("user-xdgapp:%s.desktop", xdg_app_ref_get_name (xref)); return g_strdup_printf ("user-xdgapp:%s.runtime", xdg_app_ref_get_name (xref)); }
/** * gs_plugin_refresh: */ gboolean gs_plugin_refresh (GsPlugin *plugin, guint cache_age, GsPluginRefreshFlags flags, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); guint i; g_autoptr(GPtrArray) xrefs = NULL; /* update AppStream metadata */ if (flags & GS_PLUGIN_REFRESH_FLAGS_METADATA) { if (!gs_plugin_refresh_appstream (plugin, cache_age, cancellable, error)) return FALSE; } /* no longer interesting */ if ((flags & GS_PLUGIN_REFRESH_FLAGS_PAYLOAD) == 0) return TRUE; /* get all the updates available from all remotes */ xrefs = xdg_app_installation_list_installed_refs_for_update (priv->installation, cancellable, error); if (xrefs == NULL) return FALSE; for (i = 0; i < xrefs->len; i++) { XdgAppInstalledRef *xref = g_ptr_array_index (xrefs, i); g_autoptr(GsApp) app = NULL; g_autoptr(XdgAppInstalledRef) xref2 = NULL; /* try to create a GsApp so we can do progress reporting */ app = gs_plugin_xdg_app_create_installed (plugin, xref, NULL); /* fetch but do not deploy */ g_debug ("pulling update for %s", xdg_app_ref_get_name (XDG_APP_REF (xref))); xref2 = xdg_app_installation_update (priv->installation, XDG_APP_UPDATE_FLAGS_NO_DEPLOY, xdg_app_ref_get_kind (XDG_APP_REF (xref)), xdg_app_ref_get_name (XDG_APP_REF (xref)), xdg_app_ref_get_arch (XDG_APP_REF (xref)), xdg_app_ref_get_branch (XDG_APP_REF (xref)), gs_plugin_xdg_app_progress_cb, app, cancellable, error); if (xref2 == NULL) return FALSE; } return TRUE; }
/** * gs_plugin_add_updates: */ gboolean gs_plugin_add_updates (GsPlugin *plugin, GList **list, GCancellable *cancellable, GError **error) { GsPluginData *priv = gs_plugin_get_data (plugin); guint i; g_autoptr(GPtrArray) xrefs = NULL; /* get all the installed apps (no network I/O) */ xrefs = xdg_app_installation_list_installed_refs (priv->installation, cancellable, error); if (xrefs == NULL) return FALSE; for (i = 0; i < xrefs->len; i++) { XdgAppInstalledRef *xref = g_ptr_array_index (xrefs, i); const gchar *commit; const gchar *latest_commit; g_autoptr(GsApp) app = NULL; g_autoptr(GError) error_local = NULL; /* check the application has already been downloaded */ commit = xdg_app_ref_get_commit (XDG_APP_REF (xref)); latest_commit = xdg_app_installed_ref_get_latest_commit (xref); if (g_strcmp0 (commit, latest_commit) == 0) { g_debug ("no downloaded update for %s", xdg_app_ref_get_name (XDG_APP_REF (xref))); continue; } /* we have an update to show */ g_debug ("%s has a downloaded update %s->%s", xdg_app_ref_get_name (XDG_APP_REF (xref)), commit, latest_commit); app = gs_plugin_xdg_app_create_installed (plugin, xref, &error_local); if (app == NULL) { g_warning ("failed to add xdg-app: %s", error_local->message); continue; } if (gs_app_get_state (app) == AS_APP_STATE_INSTALLED) gs_app_set_state (app, AS_APP_STATE_UNKNOWN); gs_app_set_state (app, AS_APP_STATE_UPDATABLE_LIVE); gs_app_list_add (list, app); } return TRUE; }
/** * gs_plugin_xdg_app_is_xref: */ static gboolean gs_plugin_xdg_app_is_xref (GsApp *app, XdgAppRef *xref) { g_autofree gchar *id = NULL; /* check ID */ id = gs_plugin_xdg_app_build_id (xref); if (g_strcmp0 (id, gs_app_get_id (app)) == 0) return TRUE; /* check source ID */ // if (g_strcmp0 (id, gs_app_get_id (app)) == 0) // return TRUE; /* do all the metadata items match? */ if (g_strcmp0 (gs_app_get_xdgapp_name (app), xdg_app_ref_get_name (xref)) == 0 && g_strcmp0 (gs_app_get_xdgapp_arch (app), xdg_app_ref_get_arch (xref)) == 0 && g_strcmp0 (gs_app_get_xdgapp_branch (app), xdg_app_ref_get_branch (xref)) == 0) return TRUE; /* sad panda */ return FALSE; }
/** * gs_plugin_xdg_app_set_metadata: */ static void gs_plugin_xdg_app_set_metadata (GsApp *app, XdgAppRef *xref) { gs_app_set_management_plugin (app, "xdg-app"); gs_app_set_xdgapp_kind (app, xdg_app_ref_get_kind (xref)); gs_app_set_xdgapp_name (app, xdg_app_ref_get_name (xref)); gs_app_set_xdgapp_arch (app, xdg_app_ref_get_arch (xref)); gs_app_set_xdgapp_branch (app, xdg_app_ref_get_branch (xref)); gs_app_set_xdgapp_commit (app, xdg_app_ref_get_commit (xref)); }
XdgApplication::XdgApplication(XdgAppInstalledRef *app_ref, SoftwareBackend *backend) : Application(backend) { m_state = Application::Installed; m_id = xdg_app_ref_get_name(XDG_APP_REF(app_ref)); m_branch = xdg_app_ref_get_branch(XDG_APP_REF(app_ref)); m_origin = xdg_app_installed_ref_get_origin(app_ref); m_name = m_id; m_arch = xdg_app_ref_get_arch(XDG_APP_REF(app_ref)); m_currentCommit = xdg_app_ref_get_commit(XDG_APP_REF(app_ref)); m_latestCommit = xdg_app_installed_ref_get_latest_commit(app_ref); if (m_branch.isEmpty()) m_branch = "master"; QString desktopId; switch (xdg_app_ref_get_kind(XDG_APP_REF(app_ref))) { case XDG_APP_REF_KIND_APP: m_type = Application::App; desktopId = m_name + ".desktop"; break; case XDG_APP_REF_KIND_RUNTIME: m_type = Application::Runtime; m_icon = QIcon::fromTheme("package-x-generic"); m_summary = "Framework for applications"; desktopId = m_name + ".runtime"; break; default: // TODO: Handle errors here! break; } QString deployDir = xdg_app_installed_ref_get_deploy_dir(app_ref); QString desktopPath = deployDir + "/files/share/applications"; QString appdataPath = deployDir + "/files/share/appdata"; Appstream::Store store; store.load(desktopPath); store.load(appdataPath); Appstream::Component component = store.componentById(desktopId); if (!component.isNull()) refineFromAppstream(component); }