示例#1
0
/**
 * asb_context_write_xml:
 **/
static gboolean
asb_context_write_xml (AsbContext *ctx, GError **error)
{
	AsApp *app;
	AsbContextPrivate *priv = GET_PRIVATE (ctx);
	GList *l;
	g_autofree gchar *filename = NULL;
	g_autoptr(AsStore) store = NULL;
	g_autoptr(GFile) file = NULL;

	/* convert any vetod applications into dummy components */
	for (l = priv->apps; l != NULL; l = l->next) {
		app = AS_APP (l->data);
		if (!ASB_IS_APP (app))
			continue;
		if (as_app_get_vetos(app)->len == 0)
			continue;
		asb_context_add_app_ignore (ctx, asb_app_get_package (ASB_APP (app)));
	}

	/* add any non-vetoed applications */
	store = as_store_new ();
	for (l = priv->apps; l != NULL; l = l->next) {
		app = AS_APP (l->data);
		if (as_app_get_vetos(app)->len > 0)
			continue;
		as_store_add_app (store, app);
		as_store_remove_app (priv->store_failed, app);

		/* remove from the ignore list if the application was useful */
		if (ASB_IS_APP (app)) {
			AsbPackage *pkg = asb_app_get_package (ASB_APP (app));
			g_autofree gchar *name_arch = NULL;
			name_arch = g_strdup_printf ("%s.%s",
						     asb_package_get_name (pkg),
						     asb_package_get_arch (pkg));
			as_store_remove_app_by_id (priv->store_ignore, name_arch);
		}

	}
	filename = g_strdup_printf ("%s/%s.xml.gz",
				    priv->output_dir,
				    priv->basename);
	file = g_file_new_for_path (filename);

	g_print ("Writing %s...\n", filename);
	as_store_set_origin (store, priv->origin);
	as_store_set_api_version (store, priv->api_version);
	if (priv->flags & ASB_CONTEXT_FLAG_ADD_CACHE_ID) {
		g_autofree gchar *builder_id = asb_utils_get_builder_id ();
		as_store_set_builder_id (store, builder_id);
	}
	return as_store_to_file (store,
				 file,
				 AS_NODE_TO_XML_FLAG_ADD_HEADER |
				 AS_NODE_TO_XML_FLAG_FORMAT_INDENT |
				 AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE,
				 NULL, error);
}
示例#2
0
/**
 * asb_context_write_app_xml:
 **/
static void
asb_context_write_app_xml (AsbContext *ctx)
{
	AsbApp *app;
	AsbContextPrivate *priv = GET_PRIVATE (ctx);
	GList *l;

	/* log the XML in the log file */
	for (l = priv->apps; l != NULL; l = l->next) {
		g_autoptr(GString) xml = NULL;
		g_autoptr(AsStore) store = NULL;

		/* we have an open log file? */
		if (!ASB_IS_APP (l->data))
			continue;

		/* just log raw XML */
		app = ASB_APP (l->data);
		store = as_store_new ();
		as_store_set_api_version (store, 1.0f);
		as_store_add_app (store, AS_APP (app));
		xml = as_store_to_xml (store,
				       AS_NODE_TO_XML_FLAG_FORMAT_INDENT |
				       AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
		asb_package_log (asb_app_get_package (app),
				 ASB_PACKAGE_LOG_LEVEL_NONE, "%s", xml->str);
	}
}
/**
 * asb_plugin_composite_app:
 */
static void
asb_plugin_composite_app (AsApp *app, AsApp *donor)
{
	_cleanup_error_free_ GError *error = NULL;

	/* composite the app */
	if (!_as_app_composite (app, donor, &error)) {
		if (ASB_IS_APP (app)) {
			asb_package_log (asb_app_get_package (ASB_APP (app)),
					 ASB_PACKAGE_LOG_LEVEL_INFO,
					 "%s", error->message);
		} else {
			g_warning ("%s", error->message);
		}
		return;
	}
}
示例#4
0
/**
 * asb_plugin_merge_prepare_deps:
 */
static void
asb_plugin_merge_prepare_deps (GList *list)
{
    AsApp *app;
    AsbPackage *pkg;
    GList *l;

    for (l = list; l != NULL; l = l->next) {
        app = AS_APP (l->data);
        if (as_app_get_id_kind (app) != AS_ID_KIND_DESKTOP)
            continue;
        if (!ASB_IS_APP (app))
            continue;
        if (as_app_get_vetos(app)->len > 0)
            continue;
        pkg = asb_app_get_package (ASB_APP (app));
        asb_plugin_absorb_parent_for_pkgname (list, app, asb_package_get_name (pkg));
    }
}
/**
 * asb_plugin_merge_prepare_deps:
 */
static void
asb_plugin_merge_prepare_deps (GList *list)
{
	AsApp *app;
	AsbPackage *pkg;
	GList *l;
	gchar **deps;
	guint i;

	for (l = list; l != NULL; l = l->next) {
		app = AS_APP (l->data);
		if (as_app_get_id_kind (app) != AS_ID_KIND_DESKTOP)
			continue;
		pkg = asb_app_get_package (ASB_APP (app));
		deps = asb_package_get_deps (pkg);
		for (i = 0; deps[i] != NULL; i++)
			asb_plugin_absorb_parent_for_pkgname (list, app, deps[i]);
	}
}
示例#6
0
/**
 * asb_context_save_resources:
 **/
static gboolean
asb_context_save_resources (AsbContext *ctx, GError **error)
{
	AsApp *app;
	AsbContextPrivate *priv = GET_PRIVATE (ctx);
	GList *l;

	for (l = priv->apps; l != NULL; l = l->next) {
		app = AS_APP (l->data);

		/* save icon */
		if (as_app_get_vetos(app)->len > 0)
			continue;
		if (!ASB_IS_APP (app))
			continue;
		if (!asb_app_save_resources (ASB_APP (app),
					     ASB_APP_SAVE_FLAG_ICONS,
					     error))
			return FALSE;
	}
	return TRUE;
}
示例#7
0
/**
 * asb_task_process:
 * @task: A #AsbTask
 * @error_not_used: A #GError or %NULL
 *
 * Processes the task.
 *
 * Returns: %TRUE for success, %FALSE otherwise
 *
 * Since: 0.1.0
 **/
gboolean
asb_task_process (AsbTask *task, GError **error_not_used)
{
	AsRelease *release;
	AsbApp *app;
	AsbPlugin *plugin = NULL;
	AsbTaskPrivate *priv = GET_PRIVATE (task);
	GList *apps = NULL;
	GList *l;
	GPtrArray *array;
	gboolean ret;
	gchar *cache_id;
	guint i;
	guint nr_added = 0;
	g_autoptr(GError) error = NULL;
	g_autofree gchar *basename = NULL;

	/* reset the profile timer */
	asb_package_log_start (priv->pkg);

	/* ensure nevra read */
	if (!asb_package_ensure (priv->pkg,
				 ASB_PACKAGE_ENSURE_NEVRA,
				 error_not_used))
		return FALSE;

	g_debug ("starting: %s", asb_package_get_name (priv->pkg));

	/* treat archive as a special case */
	if (g_str_has_suffix (priv->filename, ".cab")) {
		AsApp *app_tmp;
		GPtrArray *apps_tmp;
		g_autoptr(AsStore) store = as_store_new ();
		g_autoptr(GFile) file = g_file_new_for_path (priv->filename);
		if (!as_store_from_file (store, file, NULL, NULL, &error)) {
			asb_package_log (priv->pkg,
					 ASB_PACKAGE_LOG_LEVEL_WARNING,
					 "Failed to parse %s: %s",
					 asb_package_get_filename (priv->pkg),
					 error->message);
			return TRUE;
		}
		apps_tmp = as_store_get_apps (store);
		for (i = 0; i < apps_tmp->len; i++) {
			g_autoptr(AsbApp) app2 = NULL;
			app_tmp = AS_APP (g_ptr_array_index (apps_tmp, i));
			app2 = asb_app_new (priv->pkg, as_app_get_id (app_tmp));
			as_app_subsume (AS_APP (app2), app_tmp);
			asb_context_add_app (priv->ctx, app2);

			/* set cache-id in case we want to use the metadata directly */
			if (asb_context_get_flag (priv->ctx, ASB_CONTEXT_FLAG_ADD_CACHE_ID)) {
				cache_id = asb_utils_get_cache_id_for_filename (priv->filename);
				as_app_add_metadata (AS_APP (app2),
						     "X-CacheID",
						     cache_id);
				g_free (cache_id);
			}
			nr_added++;
		}
		g_debug ("added %i apps from archive", apps_tmp->len);
		goto skip;
	}

	/* ensure file list read */
	if (!asb_package_ensure (priv->pkg,
				 ASB_PACKAGE_ENSURE_FILES,
				 error_not_used))
		return FALSE;

	/* did we get a file match on any plugin */
	basename = g_path_get_basename (priv->filename);
	asb_package_log (priv->pkg,
			 ASB_PACKAGE_LOG_LEVEL_DEBUG,
			 "Getting filename match for %s",
			 basename);
	asb_task_add_suitable_plugins (task);
	if (priv->plugins_to_run->len == 0) {
		asb_context_add_app_ignore (priv->ctx, priv->pkg);
		goto out;
	}

	/* delete old tree if it exists */
	ret = asb_utils_ensure_exists_and_empty (priv->tmpdir, &error);
	if (!ret) {
		asb_package_log (priv->pkg,
				 ASB_PACKAGE_LOG_LEVEL_WARNING,
				 "Failed to clear: %s", error->message);
		goto out;
	}

	/* explode tree */
	g_debug ("decompressing files: %s", asb_package_get_name (priv->pkg));
	asb_package_log (priv->pkg,
			 ASB_PACKAGE_LOG_LEVEL_DEBUG,
			 "Exploding tree for %s",
			 asb_package_get_name (priv->pkg));
	ret = asb_package_explode (priv->pkg,
				   priv->tmpdir,
				   asb_context_get_file_globs (priv->ctx),
				   &error);
	if (!ret) {
		asb_package_log (priv->pkg,
				 ASB_PACKAGE_LOG_LEVEL_WARNING,
				 "Failed to explode: %s", error->message);
		g_clear_error (&error);
		goto skip;
	}

	/* add extra packages */
	if (!asb_package_ensure (priv->pkg,
				 ASB_PACKAGE_ENSURE_DEPS |
				 ASB_PACKAGE_ENSURE_SOURCE,
				 error_not_used))
		return FALSE;
	ret = asb_task_explode_extra_packages (task, &error);
	if (!ret) {
		asb_package_log (priv->pkg,
				 ASB_PACKAGE_LOG_LEVEL_WARNING,
				 "Failed to explode extra file: %s",
				 error->message);
		goto skip;
	}

	/* run plugins */
	g_debug ("examining: %s", asb_package_get_name (priv->pkg));
	for (i = 0; i < priv->plugins_to_run->len; i++) {
		GList *apps_tmp = NULL;
		plugin = g_ptr_array_index (priv->plugins_to_run, i);
		asb_package_log (priv->pkg,
				 ASB_PACKAGE_LOG_LEVEL_DEBUG,
				 "Processing %s with %s",
				 basename,
				 plugin->name);
		apps_tmp = asb_plugin_process (plugin, priv->pkg, priv->tmpdir, &error);
		if (apps_tmp == NULL) {
			asb_package_log (priv->pkg,
					 ASB_PACKAGE_LOG_LEVEL_WARNING,
					 "Failed to run process '%s': %s",
					 plugin->name, error->message);
			g_clear_error (&error);
		}
		for (l = apps_tmp; l != NULL; l = l->next) {
			app = ASB_APP (l->data);
			asb_plugin_add_app (&apps, AS_APP (app));
		}
		g_list_free_full (apps_tmp, g_object_unref);
	}
	if (apps == NULL)
		goto skip;

	/* print */
	g_debug ("processing: %s", asb_package_get_name (priv->pkg));
	for (l = apps; l != NULL; l = l->next) {
		app = l->data;

		/* never set */
		if (as_app_get_id (AS_APP (app)) == NULL) {
			asb_package_log (priv->pkg,
					 ASB_PACKAGE_LOG_LEVEL_INFO,
					 "app id not set for %s",
					 asb_package_get_name (priv->pkg));
			continue;
		}

		/* copy data from pkg into app */
		if (!asb_package_ensure (priv->pkg,
					 ASB_PACKAGE_ENSURE_LICENSE |
					 ASB_PACKAGE_ENSURE_RELEASES |
					 ASB_PACKAGE_ENSURE_VCS |
					 ASB_PACKAGE_ENSURE_URL,
					 error_not_used))
			return FALSE;
		if (asb_package_get_url (priv->pkg) != NULL &&
		    as_app_get_url_item (AS_APP (app), AS_URL_KIND_HOMEPAGE) == NULL) {
			as_app_add_url (AS_APP (app),
					AS_URL_KIND_HOMEPAGE,
					asb_package_get_url (priv->pkg));
		}
		if (asb_package_get_license (priv->pkg) != NULL &&
		    as_app_get_project_license (AS_APP (app)) == NULL) {
			as_app_set_project_license (AS_APP (app),
						    asb_package_get_license (priv->pkg));
		}

		/* add the source name so we can suggest these together */
		if (g_strcmp0 (asb_package_get_source_pkgname (priv->pkg),
			       asb_package_get_name (priv->pkg)) != 0) {
			as_app_set_source_pkgname (AS_APP (app),
						   asb_package_get_source_pkgname (priv->pkg));
		}

		/* set all the releases on the app */
		array = asb_package_get_releases (priv->pkg);
		for (i = 0; i < array->len; i++) {
			release = g_ptr_array_index (array, i);
			as_app_add_release (AS_APP (app), release);
		}

		/* run each refine plugin on each app */
		ret = asb_plugin_loader_process_app (asb_context_get_plugin_loader (priv->ctx),
						     priv->pkg,
						     app,
						     priv->tmpdir,
						     &error);
		if (!ret) {
			asb_package_log (priv->pkg,
					 ASB_PACKAGE_LOG_LEVEL_WARNING,
					 "Failed to run process on %s: %s",
					 as_app_get_id (AS_APP (app)),
					 error->message);
			g_clear_error (&error);
			goto skip;
		}

		/* set cache-id in case we want to use the metadata directly */
		if (asb_context_get_flag (priv->ctx, ASB_CONTEXT_FLAG_ADD_CACHE_ID)) {
			cache_id = asb_utils_get_cache_id_for_filename (priv->filename);
			as_app_add_metadata (AS_APP (app),
					     "X-CacheID",
					     cache_id);
			g_free (cache_id);
		}

		/* set the VCS information into the metadata */
		if (asb_package_get_vcs (priv->pkg) != NULL) {
			as_app_add_metadata (AS_APP (app),
					     "VersionControlSystem",
					     asb_package_get_vcs (priv->pkg));
		}

		/* save any screenshots early */
		if (array->len == 0) {
			if (!asb_app_save_resources (ASB_APP (app),
						     ASB_APP_SAVE_FLAG_SCREENSHOTS,
						     error_not_used))
				return FALSE;
		}

		/* all okay */
		asb_context_add_app (priv->ctx, app);
		nr_added++;
	}
skip:
	/* add a dummy element to the AppStream metadata so that we don't keep
	 * parsing this every time */
	if (asb_context_get_flag (priv->ctx, ASB_CONTEXT_FLAG_ADD_CACHE_ID) && nr_added == 0)
		asb_context_add_app_ignore (priv->ctx, priv->pkg);

	/* delete tree */
	g_debug ("deleting temp files: %s", asb_package_get_name (priv->pkg));
	if (!asb_utils_rmtree (priv->tmpdir, &error)) {
		asb_package_log (priv->pkg,
				 ASB_PACKAGE_LOG_LEVEL_WARNING,
				 "Failed to delete tree: %s",
				 error->message);
		goto out;
	}

	/* write log */
	g_debug ("writing log: %s", asb_package_get_name (priv->pkg));
	if (!asb_package_log_flush (priv->pkg, &error)) {
		asb_package_log (priv->pkg,
				 ASB_PACKAGE_LOG_LEVEL_WARNING,
				 "Failed to write package log: %s",
				 error->message);
		goto out;
	}
out:
	/* clear loaded resources */
	asb_package_close (priv->pkg, NULL);
	asb_package_clear (priv->pkg,
			   ASB_PACKAGE_ENSURE_DEPS |
			   ASB_PACKAGE_ENSURE_FILES);
	g_list_free_full (apps, (GDestroyNotify) g_object_unref);
	return TRUE;
}
/**
 * asb_plugin_loader_merge:
 * @plugin_loader: A #AsbPluginLoader
 * @apps: (element-type AsbApp): a list of applications that need merging
 *
 * Merge the list of applications using the plugins.
 *
 * Since: 0.2.5
 **/
void
asb_plugin_loader_merge (AsbPluginLoader *plugin_loader, GList *apps)
{
	AsbApp *app;
	AsbApp *found;
	AsbPluginLoaderPrivate *priv = GET_PRIVATE (plugin_loader);
	AsbPluginMergeFunc plugin_func = NULL;
	AsbPlugin *plugin;
	GList *l;
	const gchar *key;
	const gchar *tmp;
	gboolean ret;
	guint i;
	g_autoptr(GHashTable) hash = NULL;

	/* run each plugin */
	for (i = 0; i < priv->plugins->len; i++) {
		plugin = g_ptr_array_index (priv->plugins, i);
		ret = g_module_symbol (plugin->module,
				       "asb_plugin_merge",
				       (gpointer *) &plugin_func);
		if (!ret)
			continue;
		plugin_func (plugin, apps);
	}

	/* FIXME: move to font plugin */
	for (l = apps; l != NULL; l = l->next) {
		if (!ASB_IS_APP (l->data))
			continue;
		app = ASB_APP (l->data);
		as_app_remove_metadata (AS_APP (app), "FontFamily");
		as_app_remove_metadata (AS_APP (app), "FontFullName");
		as_app_remove_metadata (AS_APP (app), "FontIconText");
		as_app_remove_metadata (AS_APP (app), "FontParent");
		as_app_remove_metadata (AS_APP (app), "FontSampleText");
		as_app_remove_metadata (AS_APP (app), "FontSubFamily");
		as_app_remove_metadata (AS_APP (app), "FontClassifier");
	}

	/* deduplicate */
	hash = g_hash_table_new (g_str_hash, g_str_equal);
	for (l = apps; l != NULL; l = l->next) {
		if (!ASB_IS_APP (l->data))
			continue;
		app = ASB_APP (l->data);
		if (as_app_get_vetos(AS_APP(app))->len > 0)
			continue;
		key = as_app_get_id (AS_APP (app));
		found = g_hash_table_lookup (hash, key);
		if (found == NULL) {
			g_hash_table_insert (hash,
					     (gpointer) key,
					     (gpointer) app);
			continue;
		}
		if (as_app_get_kind (AS_APP (app)) == AS_APP_KIND_FIRMWARE) {
			as_app_subsume_full (AS_APP (found), AS_APP (app),
					     AS_APP_SUBSUME_FLAG_MERGE);
		}
		tmp = asb_package_get_nevr (asb_app_get_package (found));
		as_app_add_veto (AS_APP (app), "duplicate of %s", tmp);
		asb_package_log (asb_app_get_package (app),
				 ASB_PACKAGE_LOG_LEVEL_WARNING,
				 "duplicate %s not included as added from %s",
				 key, tmp);
	}
}
/**
 * _as_app_composite:
 */
static gboolean
_as_app_composite (AsApp *app, AsApp *donor, GError **error)
{
	AsApp *tmp;
	gint rc;
	_cleanup_free_ gchar *id = NULL;

	/* check this makes sense */
	if (as_app_get_id_kind (app) != as_app_get_id_kind (donor)) {
		g_set_error (error,
			     AS_APP_ERROR,
			     AS_APP_ERROR_INVALID_TYPE,
			     "Cannot composite %s:%s of different id kind",
			     as_app_get_id (app),
			     as_app_get_id (donor));
		return FALSE;
	}

	/* the ID, name with the shortest length wins */
	rc = strlen (as_app_get_id (app)) - strlen (as_app_get_id (donor));
	if (rc == 0) {
		rc = strlen (as_app_get_name (app, "C")) -
		     strlen (as_app_get_name (donor, "C"));
	}
	if (rc > 0) {
		tmp = app;
		app = donor;
		donor = tmp;
	}

	/* set the new composite string */
	id = as_utils_get_string_overlap (as_app_get_id (app), as_app_get_id (donor));
	if (id == NULL || !_as_app_is_id_valid (id)) {
		g_set_error (error,
			     AS_APP_ERROR,
			     AS_APP_ERROR_INVALID_TYPE,
			     "Cannot composite %s:%s as no ID overlap",
			     as_app_get_id (app),
			     as_app_get_id (donor));
		return FALSE;
	}


	/* log */
	if (ASB_IS_APP (app) && g_strcmp0 (as_app_get_id (app), id) != 0) {
		asb_package_log (asb_app_get_package (ASB_APP (app)),
				 ASB_PACKAGE_LOG_LEVEL_INFO,
				 "Renamed %s into %s so it could be "
				 "composited with %s",
				 as_app_get_id (app), id,
				 as_app_get_id (donor));
	}
	if (ASB_IS_APP (donor)) {
		asb_package_log (asb_app_get_package (ASB_APP (donor)),
				 ASB_PACKAGE_LOG_LEVEL_INFO,
				 "Composited %s into %s",
				 as_app_get_id (donor), id);
	}

	/* set the new ID (on both apps?) */
	as_app_set_id (app, id, -1);

	/* add some easily merged properties */
	as_app_subsume_full (app, donor, AS_APP_SUBSUME_FLAG_PARTIAL);
	as_app_add_veto (donor, "absorbed into %s", as_app_get_id (app));
	return TRUE;
}