/**
 * gs_plugin_refine_item_metadata:
 */
static gboolean
gs_plugin_refine_item_metadata (GsPlugin *plugin,
				GsApp *app,
				GCancellable *cancellable,
				GError **error)
{
	g_autoptr(XdgAppRef) xref = NULL;

	/* already set */
	if (gs_app_get_metadata_item (app, "xdg-app::kind") != NULL)
		return TRUE;

	/* AppStream sets the source to appname/arch/branch, if this isn't set
	 * we can't break out the fields */
	if (gs_app_get_source_default (app) == NULL) {
		g_warning ("no source set by appstream for %s", gs_plugin_get_name (plugin));
		return TRUE;
	}

	/* parse the ref */
	xref = xdg_app_ref_parse (gs_app_get_source_default (app), error);
	if (xref == NULL) {
		g_prefix_error (error, "failed to parse '%s': ",
				gs_app_get_source_default (app));
		return FALSE;
	}
	gs_plugin_xdg_app_set_metadata (app, xref);

	/* success */
	return TRUE;
}
예제 #2
0
/**
 * gs_plugin_refine_app:
 */
static gboolean
gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GError **error)
{
	LiPkgInfo *pki;
	g_autoptr(GError) error_local = NULL;

	/* sanity check */
	if (gs_app_get_source_default (app) == NULL)
		return TRUE;

	pki = li_manager_get_software_by_pkid (plugin->priv->mgr,
						gs_app_get_source_default (app),
						&error_local);
	if (error_local != NULL) {
		g_set_error (error,
				GS_PLUGIN_ERROR,
				GS_PLUGIN_ERROR_FAILED,
				"Unable to refine metadata: %s",
				     error_local->message);
		return FALSE;
	}

	if (pki == NULL)
		return TRUE;

	if (li_pkg_info_has_flag (pki, LI_PACKAGE_FLAG_INSTALLED))
		gs_app_set_state (app, AS_APP_STATE_INSTALLED);
	else
		gs_app_set_state (app, AS_APP_STATE_AVAILABLE);

	gs_app_set_version (app, li_pkg_info_get_version (pki));

	return TRUE;
}
예제 #3
0
gboolean
gs_plugin_refine_app (GsPlugin *plugin,
		      GsApp *app,
		      GsPluginRefineFlags flags,
		      GCancellable *cancellable,
		      GError **error)
{
	GsPluginData *priv = gs_plugin_get_data (plugin);
	LiPkgInfo *pki;
	g_autoptr(GError) error_local = NULL;
	g_autoptr(AsProfileTask) ptask = NULL;

	/* not us */
	if (g_strcmp0 (gs_app_get_management_plugin (app),
		       gs_plugin_get_name (plugin)) != 0)
		return TRUE;

	/* profile */
	ptask = as_profile_start (gs_plugin_get_profile (plugin),
				  "limba::refine{%s}",
				  gs_app_get_id (app));

	/* sanity check */
	if (gs_app_get_source_default (app) == NULL)
		return TRUE;

	pki = li_manager_get_software_by_pkid (priv->mgr,
						gs_app_get_source_default (app),
						&error_local);
	if (error_local != NULL) {
		g_set_error (error,
				GS_PLUGIN_ERROR,
				GS_PLUGIN_ERROR_FAILED,
				"Unable to refine metadata: %s",
				     error_local->message);
		return FALSE;
	}

	if (pki == NULL)
		return TRUE;

	if (li_pkg_info_has_flag (pki, LI_PACKAGE_FLAG_INSTALLED))
		gs_app_set_state (app, AS_APP_STATE_INSTALLED);
	else
		gs_app_set_state (app, AS_APP_STATE_AVAILABLE);

	gs_app_set_version (app, li_pkg_info_get_version (pki));

	return TRUE;
}
/**
 * gs_plugin_refine:
 */
gboolean
gs_plugin_refine (GsPlugin *plugin,
		  GList **list,
		  GsPluginRefineFlags flags,
		  GCancellable *cancellable,
		  GError **error)
{
	GList *l;
	GPtrArray *sources;
	GsApp *app;
	const gchar *pkgname;
	gboolean ret;
	gint rating;
	gint confidence;
	guint i;

	/* nothing to do here */
	if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_RATING) == 0)
		return TRUE;

	/* already loaded */
	if (g_once_init_enter (&plugin->priv->loaded)) {
		ret = gs_plugin_fedora_tagger_load_db (plugin, error);
		g_once_init_leave (&plugin->priv->loaded, TRUE);
		if (!ret)
			return FALSE;
	}

	/* add any missing ratings data */
	for (l = *list; l != NULL; l = l->next) {
		app = GS_APP (l->data);
		if (gs_app_get_rating (app) != -1)
			continue;
		sources = gs_app_get_sources (app);
		for (i = 0; i < sources->len; i++) {
			pkgname = g_ptr_array_index (sources, i);
			ret = gs_plugin_resolve_app (plugin,
						     pkgname,
						     &rating,
						     &confidence,
						     error);
			if (!ret)
				return FALSE;
			if (rating != -1) {
				g_debug ("fedora-tagger setting rating on %s to %i%% [%i]",
					 pkgname, rating, confidence);
				gs_app_set_rating (app, rating);
				gs_app_set_rating_confidence (app, confidence);
				gs_app_set_rating_kind (app, GS_APP_RATING_KIND_SYSTEM);
				if (confidence > 50 && rating > 80) {
					g_debug ("%s is popular [confidence %i]",
						 gs_app_get_source_default (app),
						 confidence);
					gs_app_add_kudo (app, GS_APP_KUDO_POPULAR);
				}
			}
		}
	}
	return TRUE;
}
예제 #5
0
static gboolean
gs_plugin_add_sources_related (GsPlugin *plugin,
			       GHashTable *hash,
			       GCancellable *cancellable,
			       GError **error)
{
	GsPluginData *priv = gs_plugin_get_data (plugin);
	guint i;
	GsApp *app;
	GsApp *app_tmp;
	PkBitfield filter;
	ProgressData data;
	const gchar *id;
	gboolean ret = TRUE;
	g_autoptr(GsAppList) installed = gs_app_list_new ();
	g_autoptr(PkResults) results = NULL;
	g_autoptr(AsProfileTask) ptask = NULL;

	data.app = NULL;
	data.plugin = plugin;
	data.ptask = NULL;

	ptask = as_profile_start_literal (gs_plugin_get_profile (plugin),
					  "packagekit::add-sources-related");
	g_assert (ptask != NULL);
	filter = pk_bitfield_from_enums (PK_FILTER_ENUM_INSTALLED,
					 PK_FILTER_ENUM_NEWEST,
					 PK_FILTER_ENUM_ARCH,
					 PK_FILTER_ENUM_NOT_COLLECTIONS,
					 -1);
	results = pk_client_get_packages (PK_CLIENT(priv->task),
					   filter,
					   cancellable,
					   gs_plugin_packagekit_progress_cb, &data,
					   error);
	if (!gs_plugin_packagekit_results_valid (results, error))
		return FALSE;
	ret = gs_plugin_packagekit_add_results (plugin,
						installed,
						results,
						error);
	if (!ret)
		return FALSE;
	for (i = 0; i < gs_app_list_length (installed); i++) {
		g_auto(GStrv) split = NULL;
		app = gs_app_list_index (installed, i);
		split = pk_package_id_split (gs_app_get_source_id_default (app));
		if (g_str_has_prefix (split[PK_PACKAGE_ID_DATA], "installed:")) {
			id = split[PK_PACKAGE_ID_DATA] + 10;
			app_tmp = g_hash_table_lookup (hash, id);
			if (app_tmp != NULL) {
				g_debug ("found package %s from %s",
					 gs_app_get_source_default (app), id);
				gs_app_add_related (app_tmp, app);
			}
		}
	}
	return TRUE;
}
예제 #6
0
gboolean
gs_plugin_app_install (GsPlugin *plugin,
			GsApp *app,
			GCancellable *cancellable,
			GError **error)
{
	g_autoptr(LiInstaller) inst = NULL;
	GsPluginHelper helper;
	g_autoptr(GError) error_local = NULL;

	/* not us */
	if (g_strcmp0 (gs_app_get_management_plugin (app),
		       gs_plugin_get_name (plugin)) != 0)
		return TRUE;

	/* create new installer and select remote package */
	inst = li_installer_new ();
	li_installer_open_remote (inst,
				  gs_app_get_source_default (app),
				  &error_local);
	if (error_local != NULL) {
		g_set_error (error,
				GS_PLUGIN_ERROR,
				GS_PLUGIN_ERROR_FAILED,
				"Failed to install software: %s",
				     error_local->message);
		return FALSE;
	}

	/* set up progress forwarding */
	helper.app = app;
	helper.plugin = plugin;
	g_signal_connect (inst,
			  "progress",
			  G_CALLBACK (gs_plugin_installer_progress_cb),
			  &helper);

	/* install software */
	gs_app_set_state (app, AS_APP_STATE_INSTALLING);
	li_installer_install (inst, &error_local);
	if (error_local != NULL) {
		gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
		g_set_error (error,
				GS_PLUGIN_ERROR,
				GS_PLUGIN_ERROR_FAILED,
				"Failed to install software: %s",
				     error_local->message);
		return FALSE;
	}

	gs_app_set_state (app, AS_APP_STATE_INSTALLED);

	return TRUE;
}
예제 #7
0
gboolean
gs_plugin_app_remove (GsPlugin *plugin,
			GsApp *app,
			GCancellable *cancellable,
			GError **error)
{
	g_autoptr(LiManager) mgr = NULL;
	GsPluginHelper helper;
	g_autoptr(GError) error_local = NULL;

	/* not us */
	if (g_strcmp0 (gs_app_get_management_plugin (app),
		       gs_plugin_get_name (plugin)) != 0)
		return TRUE;

	mgr = li_manager_new ();

	/* set up progress forwarding */
	helper.app = app;
	helper.plugin = plugin;
	g_signal_connect (mgr,
			  "progress",
			  G_CALLBACK (gs_plugin_manager_progress_cb),
			  &helper);

	gs_app_set_state (app, AS_APP_STATE_REMOVING);
	li_manager_remove_software (mgr,
				    gs_app_get_source_default (app),
				    &error_local);
	if (error_local != NULL) {
		gs_app_set_state (app, AS_APP_STATE_INSTALLED);
		g_set_error (error,
				GS_PLUGIN_ERROR,
				GS_PLUGIN_ERROR_FAILED,
				"Failed to remove software: %s",
				     error_local->message);
		return FALSE;
	}

	gs_app_set_state (app, AS_APP_STATE_AVAILABLE);

	return TRUE;
}
gboolean
gs_plugin_refine (GsPlugin *plugin,
		  GsAppList *list,
		  GsPluginRefineFlags flags,
		  GCancellable *cancellable,
		  GError **error)
{
	g_autoptr(GsApp) app = NULL;
	g_autoptr(GsAppList) os_updates = gs_app_list_new ();

	/* not from get_updates() */
	if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_UPDATE_DETAILS) == 0)
		return TRUE;

	/* do we have any packages left that are not apps? */
	for (guint i = 0; i < gs_app_list_length (list); i++) {
		GsApp *app_tmp = gs_app_list_index (list, i);
		if (gs_plugin_generic_updates_merge_os_update (app_tmp))
			gs_app_list_add (os_updates, app_tmp);
	}
	if (gs_app_list_length (os_updates) == 0)
		return TRUE;

	/* create new meta object */
	app = gs_plugin_generic_updates_get_os_update (plugin);
	for (guint i = 0; i < gs_app_list_length (os_updates); i++) {
		GsApp *app_tmp = gs_app_list_index (os_updates, i);
		const gchar *id = gs_app_get_unique_id (app_tmp);
		if (id == NULL)
			id = gs_app_get_source_default (app_tmp);
		g_debug ("moving %s to parent %s",
			 id, gs_app_get_unique_id (app));
		gs_app_add_related (app, app_tmp);
		gs_app_list_remove (list, app_tmp);
	}
	gs_app_list_add (list, app);
	return TRUE;
}
/**
 * gs_plugin_app_install:
 */
gboolean
gs_plugin_app_install (GsPlugin *plugin,
		       GsApp *app,
		       GCancellable *cancellable,
		       GError **error)
{
	GsPluginData *priv = gs_plugin_get_data (plugin);
	g_autoptr(XdgAppInstalledRef) xref = 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;

	/* ensure we have metadata and state */
	if (!gs_plugin_xdg_app_refine_app (plugin, app, 0, cancellable, error))
		return FALSE;

	/* install */
	gs_app_set_state (app, AS_APP_STATE_INSTALLING);

	/* install required runtime if not already installed */
	if (gs_app_get_kind (app) == AS_APP_KIND_DESKTOP) {
		GsApp *runtime;
		runtime = gs_app_get_runtime (app);

		/* the runtime could come from a different remote to the app */
		if (!gs_plugin_refine_item_metadata (plugin, runtime, cancellable, error))
			return FALSE;
		if (!gs_plugin_refine_item_origin (plugin, runtime, cancellable, error))
			return FALSE;
		if (!gs_plugin_refine_item_state (plugin, runtime, cancellable, error))
			return FALSE;
		if (gs_app_get_state (runtime) == AS_APP_STATE_UNKNOWN) {
			g_set_error (error,
				     GS_PLUGIN_ERROR,
				     GS_PLUGIN_ERROR_NOT_SUPPORTED,
				     "Failed to find runtime %s",
				     gs_app_get_source_default (runtime));
			return FALSE;
		}

		/* not installed */
		if (gs_app_get_state (runtime) == AS_APP_STATE_AVAILABLE) {
			g_debug ("%s is not already installed, so installing",
				 gs_app_get_id (runtime));
			gs_app_set_state (runtime, AS_APP_STATE_INSTALLING);
			xref = xdg_app_installation_install (priv->installation,
							     gs_app_get_origin (runtime),
							     gs_app_get_xdgapp_kind (runtime),
							     gs_app_get_xdgapp_name (runtime),
							     gs_app_get_xdgapp_arch (runtime),
							     gs_app_get_xdgapp_branch (runtime),
							     gs_plugin_xdg_app_progress_cb, app,
							     cancellable, error);
			if (xref == NULL) {
				gs_app_set_state_recover (runtime);
				return FALSE;
			}
			gs_app_set_state (runtime, AS_APP_STATE_INSTALLED);
		} else {
			g_debug ("%s is already installed, so skipping",
				 gs_app_get_id (runtime));
		}
	}

	/* use the source for local apps */
	if (gs_app_get_state (app) == AS_APP_STATE_AVAILABLE_LOCAL) {
		xref = xdg_app_installation_install_bundle (priv->installation,
							    gs_app_get_local_file (app),
							    gs_plugin_xdg_app_progress_cb,
							    app,
							    cancellable, error);
	} else {
		g_debug ("installing %s", gs_app_get_id (app));
		xref = xdg_app_installation_install (priv->installation,
						     gs_app_get_origin (app),
						     gs_app_get_xdgapp_kind (app),
						     gs_app_get_xdgapp_name (app),
						     gs_app_get_xdgapp_arch (app),
						     gs_app_get_xdgapp_branch (app),
						     gs_plugin_xdg_app_progress_cb, app,
						     cancellable, error);
	}
	if (xref == NULL) {
		gs_app_set_state_recover (app);
		return FALSE;
	}

	/* state is known */
	gs_app_set_state (app, AS_APP_STATE_INSTALLED);
	return TRUE;
}
예제 #10
0
gboolean
gs_plugin_update_app (GsPlugin *plugin,
		      GsApp *app,
		      GCancellable *cancellable,
		      GError **error)
{
	GsPluginHelper helper;
	g_autoptr(LiManager) mgr = NULL;
	LiUpdateItem *uitem;
	g_autoptr(GError) error_local = NULL;

	/* sanity check */
	if (gs_app_get_source_default (app) == NULL) {
		g_set_error (error,
				GS_PLUGIN_ERROR,
				GS_PLUGIN_ERROR_FAILED,
				"Failed to run update: Default source was NULL.");
		return FALSE;
	}

	mgr = li_manager_new ();

	/* set up progress forwarding */
	helper.app = app;
	helper.plugin = plugin;
	g_signal_connect (mgr,
			  "progress",
			  G_CALLBACK (gs_plugin_manager_progress_cb),
			  &helper);

	/* find update which matches the ID we have */
	uitem = li_manager_get_update_for_id (mgr,
					      gs_app_get_source_default (app),
					      &error_local);
	if (error_local != NULL) {
		g_set_error (error,
				GS_PLUGIN_ERROR,
				GS_PLUGIN_ERROR_FAILED,
				"Failed to find update: %s",
				error_local->message);
		return FALSE;
	}

	if (uitem == NULL) {
		g_set_error (error,
				GS_PLUGIN_ERROR,
				GS_PLUGIN_ERROR_FAILED,
				"Could not find update for '%s'.",
				gs_app_get_source_default (app));
		return FALSE;
	}

	gs_app_set_state (app, AS_APP_STATE_INSTALLING);
	li_manager_update (mgr, uitem, &error_local);
	if (error_local != NULL) {
		g_set_error (error,
				GS_PLUGIN_ERROR,
				GS_PLUGIN_ERROR_FAILED,
				"Software update failed: %s",
				error_local->message);
		gs_app_set_state (app, AS_APP_STATE_UPDATABLE_LIVE);
		return FALSE;
	}
	gs_app_set_state (app, AS_APP_STATE_INSTALLED);

	return TRUE;
}
예제 #11
0
/**
 * gs_plugin_refine_app:
 */
gboolean
gs_plugin_refine_app (GsPlugin *plugin,
		      GsApp *app,
		      GsPluginRefineFlags flags,
		      GCancellable *cancellable,
		      GError **error)
{
	Header h;
	const gchar *fn;
	gint rc;
	g_auto(rpmdbMatchIterator) mi = NULL;
	g_auto(rpmts) ts = NULL;

	/* not required */
	if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION) == 0 &&
	    (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_SIZE) == 0 &&
	    (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE) == 0 &&
	    (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_SETUP_ACTION) == 0)
		return TRUE;

	/* no need to run the plugin */
	if (gs_app_get_source_default (app) != NULL &&
	    gs_app_get_source_id_default (app) != NULL)
		return TRUE;

	/* open db readonly */
	ts = rpmtsCreate();
	rpmtsSetRootDir (ts, NULL);
	rc = rpmtsOpenDB (ts, O_RDONLY);
	if (rc != 0) {
		g_set_error (error,
			     GS_PLUGIN_ERROR,
			     GS_PLUGIN_ERROR_FAILED,
			     "Failed to open rpmdb: %i", rc);
		return FALSE;
	}

	/* look for a specific file */
	fn = gs_app_get_metadata_item (app, "appstream::source-file");
	if (fn == NULL)
		return TRUE;
	if (!g_str_has_prefix (fn, "/usr"))
		return TRUE;
	mi = rpmtsInitIterator (ts, RPMDBI_INSTFILENAMES, fn, 0);
	if (mi == NULL) {
		g_debug ("rpm: no search results for %s", fn);
		return TRUE;
	}

	/* on rpm-ostree this package cannot be removed 'live' */
	gs_app_add_quirk (app, AS_APP_QUIRK_COMPULSORY);

	/* process any results */
	g_debug ("rpm: querying for %s with %s", gs_app_get_id (app), fn);
	while ((h = rpmdbNextIterator (mi)) != NULL) {
		guint64 epoch;
		const gchar *name;
		const gchar *version;
		const gchar *arch;
		const gchar *release;
		const gchar *license;

		/* add default source */
		name = headerGetString (h, RPMTAG_NAME);
		if (gs_app_get_source_default (app) == NULL) {
			g_debug ("rpm: setting source to %s", name);
			gs_app_add_source (app, name);
		}

		/* set size */
		if (gs_app_get_size_download (app) == 0)
			gs_app_set_size_download (app, 0);
		if (gs_app_get_size_installed (app) == 0) {
			guint64 tmp;
			tmp = headerGetNumber (h, RPMTAG_SIZE);
			gs_app_set_size_installed (app, tmp);
		}

		/* set license */
		license = headerGetString (h, RPMTAG_LICENSE);
		if (gs_app_get_license (app) == NULL && license != NULL) {
			g_autofree gchar *tmp = NULL;
			tmp = as_utils_license_to_spdx (license);
			gs_app_set_license (app, GS_APP_QUALITY_NORMAL, tmp);
		}

		/* add version */
		version = headerGetString (h, RPMTAG_VERSION);
		if (gs_app_get_version (app) == NULL) {
			g_debug ("rpm: setting version to %s", version);
			gs_app_set_version (app, version);
		}

		/* add source-id */
		if (gs_app_get_source_id_default (app) == NULL) {
			g_autofree gchar *tmp = NULL;
			release = headerGetString (h, RPMTAG_RELEASE);
			arch = headerGetString (h, RPMTAG_ARCH);
			epoch = headerGetNumber (h, RPMTAG_EPOCH);
			if (epoch > 0) {
				tmp = g_strdup_printf ("%s;%" G_GUINT64_FORMAT ":%s-%s;%s;installed",
						       name, epoch, version, release, arch);
			} else {
				tmp = g_strdup_printf ("%s;%s-%s;%s;installed",
						       name, version, release, arch);
			}
			g_debug ("rpm: setting source-id to %s", tmp);
			gs_app_add_source_id (app, tmp);
		}
	}

	return TRUE;
}
gboolean
gs_plugin_review_submit (GsPlugin *plugin,
			 GsApp *app,
			 AsReview *review,
			 GCancellable *cancellable,
			 GError **error)
{
	GsPluginData *priv = gs_plugin_get_data (plugin);
	GsAuth *auth;
	const gchar *consumer_key = NULL;
	const gchar *language;
	gint rating;
	gint n_stars;
	g_autofree gchar *architecture = NULL;
	g_autoptr(JsonBuilder) request = NULL;
	guint status_code;
	g_autoptr(JsonParser) result = NULL;

	/* Ubuntu reviews require a summary and description - just make one up for now */
	rating = as_review_get_rating (review);
	if (rating > 80)
		n_stars = 5;
	else if (rating > 60)
		n_stars = 4;
	else if (rating > 40)
		n_stars = 3;
	else if (rating > 20)
		n_stars = 2;
	else
		n_stars = 1;

	language = gs_plugin_get_language (plugin);

	// FIXME: Need to get Apt::Architecture configuration value from APT
	architecture = g_strdup ("amd64");

	/* Create message for reviews.ubuntu.com */
	request = json_builder_new ();
	json_builder_begin_object (request);
	add_string_member (request, "package_name", gs_app_get_source_default (app));
	add_string_member (request, "summary", as_review_get_summary (review));
	add_string_member (request, "review_text", as_review_get_description (review));
	add_string_member (request, "language", language);
	add_string_member (request, "origin", priv->origin);
	add_string_member (request, "distroseries", priv->distroseries);
	add_string_member (request, "version", as_review_get_version (review));
	add_int_member (request, "rating", n_stars);
	add_string_member (request, "arch_tag", architecture);
	json_builder_end_object (request);

	if (!send_review_request (plugin, SOUP_METHOD_POST, "/api/1.0/reviews/",
				  request, TRUE,
				  &status_code, &result, cancellable, error))
		return FALSE;

	if (status_code != SOUP_STATUS_OK) {
		g_set_error (error,
			     GS_PLUGIN_ERROR,
			     GS_PLUGIN_ERROR_FAILED,
			     "Failed to submit review, server returned status code %u",
			     status_code);
		return FALSE;
	}

	// Extract new fields from posted review
	auth = gs_plugin_get_auth_by_id (plugin, "ubuntuone");
	if (auth != NULL)
		consumer_key = gs_auth_get_metadata_item (auth, "consumer-key");
	parse_review (review, consumer_key, json_parser_get_root (result));

	return TRUE;
}