summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libappstream-glib/as-app-private.h3
-rw-r--r--libappstream-glib/as-app.c4
-rw-r--r--libappstream-glib/as-self-test.c17
-rw-r--r--libappstream-glib/as-store.c98
-rw-r--r--libappstream-glib/as-store.h17
5 files changed, 137 insertions, 2 deletions
diff --git a/libappstream-glib/as-app-private.h b/libappstream-glib/as-app-private.h
index 91e9399..dd6f357 100644
--- a/libappstream-glib/as-app-private.h
+++ b/libappstream-glib/as-app-private.h
@@ -79,6 +79,9 @@ typedef enum {
#define AS_APP_ICON_MIN_HEIGHT 32
#define AS_APP_ICON_MIN_WIDTH 32
+/* unique */
+#define AS_APP_UNIQUE_WILDCARD "*"
+
AsAppProblems as_app_get_problems (AsApp *app);
guint as_app_get_name_size (AsApp *app);
guint as_app_get_comment_size (AsApp *app);
diff --git a/libappstream-glib/as-app.c b/libappstream-glib/as-app.c
index d8f1d0d..b3bfed3 100644
--- a/libappstream-glib/as-app.c
+++ b/libappstream-glib/as-app.c
@@ -514,7 +514,7 @@ static const gchar *
as_app_fix_unique_nullable (const gchar *tmp)
{
if (tmp == NULL || tmp[0] == '\0')
- return "*";
+ return AS_APP_UNIQUE_WILDCARD;
return tmp;
}
@@ -535,7 +535,7 @@ as_app_get_unique_id_system (AsApp *app)
return "package";
/* nothing */
- return "*";
+ return AS_APP_UNIQUE_WILDCARD;
}
/**
diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c
index 6dde169..cb047e8 100644
--- a/libappstream-glib/as-self-test.c
+++ b/libappstream-glib/as-self-test.c
@@ -2987,6 +2987,23 @@ as_test_store_prefix_func (void)
app_tmp = g_ptr_array_index (apps, 0);
g_assert_cmpstr (as_app_get_id (app_tmp), ==,
"flatpak-user:org.gnome.Software.desktop");
+
+ /* exact unique match */
+ app_tmp = as_store_get_app_by_unique_id (store, "*/*/*/*/test/*/*",
+ AS_STORE_SEARCH_FLAG_NONE);
+ g_assert (app_tmp == NULL);
+ app_tmp = as_store_get_app_by_unique_id (store, "*/*/*/*/test/*/*",
+ AS_STORE_SEARCH_FLAG_USE_WILDCARDS);
+ g_assert (app_tmp == NULL);
+ app_tmp = as_store_get_app_by_unique_id (store, "*/*/*/*/org.gnome.Software.desktop/*/*",
+ AS_STORE_SEARCH_FLAG_NONE);
+ g_assert (app_tmp != NULL);
+ app_tmp = as_store_get_app_by_unique_id (store, "*/*/*/*/org.gnome.Software.desktop/*/*",
+ AS_STORE_SEARCH_FLAG_USE_WILDCARDS);
+ g_assert (app_tmp != NULL);
+// app_tmp = as_store_get_app_by_unique_id (store, "*/*/*/*/*/*/*",
+// AS_STORE_SEARCH_FLAG_USE_WILDCARDS);
+// g_assert (app_tmp != NULL);
}
/* load a store with a origin and scope encoded in the symlink name */
diff --git a/libappstream-glib/as-store.c b/libappstream-glib/as-store.c
index 00a6a77..a3b533c 100644
--- a/libappstream-glib/as-store.c
+++ b/libappstream-glib/as-store.c
@@ -65,6 +65,7 @@ typedef struct
gdouble api_version;
GPtrArray *array; /* of AsApp */
GHashTable *hash_id; /* of AsApp{id} */
+ GHashTable *hash_unique_id; /* of AsApp{unique_id} */
GHashTable *hash_pkgname; /* of AsApp{pkgname} */
AsMonitor *monitor;
GHashTable *metadata_indexes; /* GHashTable{key} */
@@ -123,6 +124,7 @@ as_store_finalize (GObject *object)
g_object_unref (priv->monitor);
g_object_unref (priv->profile);
g_hash_table_unref (priv->hash_id);
+ g_hash_table_unref (priv->hash_unique_id);
g_hash_table_unref (priv->hash_pkgname);
g_hash_table_unref (priv->metadata_indexes);
g_hash_table_unref (priv->appinfo_dirs);
@@ -293,6 +295,7 @@ as_store_remove_all (AsStore *store)
g_return_if_fail (AS_IS_STORE (store));
g_ptr_array_set_size (priv->array, 0);
g_hash_table_remove_all (priv->hash_id);
+ g_hash_table_remove_all (priv->hash_unique_id);
g_hash_table_remove_all (priv->hash_pkgname);
}
@@ -453,6 +456,90 @@ as_store_get_app_by_id (AsStore *store, const gchar *id)
return g_hash_table_lookup (priv->hash_id, id);
}
+static AsApp *
+_as_app_new_from_unique_id (const gchar *unique_id)
+{
+ g_auto(GStrv) split = NULL;
+ g_autoptr(AsApp) app = as_app_new ();
+
+ split = g_strsplit (unique_id, "/", -1);
+ if (g_strv_length (split) != 7)
+ return NULL;
+ if (g_strcmp0 (split[0], AS_APP_UNIQUE_WILDCARD) != 0)
+ as_app_set_scope (app, as_app_scope_from_string (split[1]));
+ if (g_strcmp0 (split[2], AS_APP_UNIQUE_WILDCARD) != 0) {
+ if (g_strcmp0 (split[2], "package") == 0) {
+ as_app_add_pkgname (app, "");
+ } else {
+ AsBundleKind kind = as_bundle_kind_from_string (split[2]);
+ if (kind != AS_BUNDLE_KIND_UNKNOWN) {
+ AsBundle *bundle = as_bundle_new ();
+ as_bundle_set_kind (bundle, kind);
+ as_app_add_bundle (app, bundle);
+ }
+ }
+ }
+ if (g_strcmp0 (split[2], AS_APP_UNIQUE_WILDCARD) != 0)
+ as_app_set_origin (app, split[2]);
+ if (g_strcmp0 (split[3], AS_APP_UNIQUE_WILDCARD) != 0)
+ as_app_set_kind (app, as_app_kind_from_string (split[3]));
+ if (g_strcmp0 (split[4], AS_APP_UNIQUE_WILDCARD) != 0)
+ as_app_set_id (app, split[4]);
+ if (g_strcmp0 (split[5], AS_APP_UNIQUE_WILDCARD) != 0)
+ as_app_add_arch (app, split[5]);
+ if (g_strcmp0 (split[6], AS_APP_UNIQUE_WILDCARD) != 0)
+ as_app_set_branch (app, split[6]);
+
+ return g_steal_pointer (&app);
+}
+
+static AsApp *
+as_store_get_app_by_app (AsStore *store, AsApp *app)
+{
+ AsStorePrivate *priv = GET_PRIVATE (store);
+ guint i;
+
+ for (i = 0; i < priv->array->len; i++) {
+ AsApp *app_tmp = g_ptr_array_index (priv->array, i);
+ if (as_app_equal (app_tmp, app))
+ return app_tmp;
+ }
+ return NULL;
+}
+
+/**
+ * as_store_get_app_by_unique_id:
+ * @store: a #AsStore instance.
+ * @unique_id: the application unique ID, e.g.
+ * `user/flatpak/gnome-apps-nightly/app/gimp.desktop/i386/master`
+ * @search_flags: the search flags, e.g. %AS_STORE_SEARCH_FLAG_USE_WILDCARDS
+ *
+ * Finds an application in the store by matching the unique ID.
+ *
+ * Returns: (transfer none): a #AsApp or %NULL
+ *
+ * Since: 0.6.1
+ **/
+AsApp *
+as_store_get_app_by_unique_id (AsStore *store,
+ const gchar *unique_id,
+ AsStoreSearchFlags search_flags)
+{
+ AsStorePrivate *priv = GET_PRIVATE (store);
+ g_autoptr(AsApp) app_tmp = NULL;
+
+ g_return_val_if_fail (AS_IS_STORE (store), NULL);
+ g_return_val_if_fail (unique_id != NULL, NULL);
+
+ /* no globs */
+ if ((search_flags & AS_STORE_SEARCH_FLAG_USE_WILDCARDS) == 0)
+ return g_hash_table_lookup (priv->hash_unique_id, unique_id);
+
+ /* create virtual app using scope/system/origin/kind/id/arch/branch */
+ app_tmp = _as_app_new_from_unique_id (unique_id);
+ return as_store_get_app_by_app (store, app_tmp);
+}
+
/**
* as_store_get_app_by_provide:
* @store: a #AsStore instance.
@@ -743,6 +830,7 @@ as_store_remove_app (AsStore *store, AsApp *app)
{
AsStorePrivate *priv = GET_PRIVATE (store);
g_hash_table_remove (priv->hash_id, as_app_get_id (app));
+ g_hash_table_remove (priv->hash_unique_id, as_app_get_unique_id (app));
g_ptr_array_remove (priv->array, app);
g_hash_table_remove_all (priv->metadata_indexes);
@@ -773,6 +861,8 @@ as_store_remove_app_by_id (AsStore *store, const gchar *id)
if (g_strcmp0 (id, as_app_get_id (app)) != 0)
continue;
g_ptr_array_remove (priv->array, app);
+ g_hash_table_remove (priv->hash_unique_id,
+ as_app_get_unique_id (app));
}
g_hash_table_remove_all (priv->metadata_indexes);
@@ -887,6 +977,7 @@ as_store_add_app (AsStore *store, AsApp *app)
as_app_source_kind_to_string (as_app_get_source_kind (item)),
id);
g_hash_table_remove (priv->hash_id, id);
+ g_hash_table_remove (priv->hash_unique_id, id);
g_ptr_array_remove (priv->array, item);
}
@@ -895,6 +986,9 @@ as_store_add_app (AsStore *store, AsApp *app)
g_hash_table_insert (priv->hash_id,
(gpointer) as_app_get_id (app),
app);
+ g_hash_table_insert (priv->hash_unique_id,
+ (gpointer) as_app_get_unique_id (app),
+ app);
pkgnames = as_app_get_pkgnames (app);
for (i = 0; i < pkgnames->len; i++) {
pkgname = g_ptr_array_index (pkgnames, i);
@@ -2893,6 +2987,10 @@ as_store_init (AsStore *store)
g_str_equal,
NULL,
NULL);
+ priv->hash_unique_id = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ NULL,
+ NULL);
priv->hash_pkgname = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
diff --git a/libappstream-glib/as-store.h b/libappstream-glib/as-store.h
index efb1b1b..8465ce1 100644
--- a/libappstream-glib/as-store.h
+++ b/libappstream-glib/as-store.h
@@ -116,6 +116,20 @@ typedef enum {
} AsStoreWatchFlags;
/**
+ * AsStoreSearchFlags:
+ * @AS_STORE_SEARCH_FLAG_NONE: No extra flags to use
+ * @AS_STORE_SEARCH_FLAG_USE_WILDCARDS: Process the globs
+ *
+ * The flags to use when searching in the store.
+ **/
+typedef enum {
+ AS_STORE_SEARCH_FLAG_NONE = 0, /* Since: 0.6.1 */
+ AS_STORE_SEARCH_FLAG_USE_WILDCARDS = 1, /* Since: 0.6.1 */
+ /*< private >*/
+ AS_STORE_SEARCH_FLAG_LAST
+} AsStoreSearchFlags;
+
+/**
* AsStoreError:
* @AS_STORE_ERROR_FAILED: Generic failure
*
@@ -166,6 +180,9 @@ GPtrArray *as_store_get_apps_by_metadata (AsStore *store,
const gchar *value);
AsApp *as_store_get_app_by_id (AsStore *store,
const gchar *id);
+AsApp *as_store_get_app_by_unique_id (AsStore *store,
+ const gchar *unique_id,
+ AsStoreSearchFlags search_flags);
AsApp *as_store_get_app_by_id_ignore_prefix
(AsStore *store,
const gchar *id);