diff options
author | Richard Hughes <richard@hughsie.com> | 2014-03-20 15:41:04 +0000 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2014-03-20 17:54:52 +0000 |
commit | 50fc0be57d11b757c78b1b2445f4a9d7137a243d (patch) | |
tree | 6175aea257681c9c7a605493515e39655517a556 | |
parent | 2f4dc7bdbc3b407889f239d87b2b1ae018e3a2d8 (diff) | |
download | appstream-glib-50fc0be57d11b757c78b1b2445f4a9d7137a243d.tar.gz |
Add an 'api-version' property to AsStore to generate old-style metadata
This allows us to keep up with the latest API and still write metadata
compatible with old applications not using libappstream-glib or libappstream.
-rw-r--r-- | libappstream-glib/as-app-private.h | 3 | ||||
-rw-r--r-- | libappstream-glib/as-app.c | 92 | ||||
-rw-r--r-- | libappstream-glib/as-image-private.h | 3 | ||||
-rw-r--r-- | libappstream-glib/as-image.c | 3 | ||||
-rw-r--r-- | libappstream-glib/as-node.c | 9 | ||||
-rw-r--r-- | libappstream-glib/as-node.h | 2 | ||||
-rw-r--r-- | libappstream-glib/as-release-private.h | 3 | ||||
-rw-r--r-- | libappstream-glib/as-release.c | 7 | ||||
-rw-r--r-- | libappstream-glib/as-screenshot-private.h | 3 | ||||
-rw-r--r-- | libappstream-glib/as-screenshot.c | 12 | ||||
-rw-r--r-- | libappstream-glib/as-self-test.c | 110 | ||||
-rw-r--r-- | libappstream-glib/as-store.c | 61 | ||||
-rw-r--r-- | libappstream-glib/as-store.h | 3 | ||||
-rw-r--r-- | libappstream-glib/as-tag.c | 8 |
14 files changed, 263 insertions, 56 deletions
diff --git a/libappstream-glib/as-app-private.h b/libappstream-glib/as-app-private.h index 6d508b1..48f8de3 100644 --- a/libappstream-glib/as-app-private.h +++ b/libappstream-glib/as-app-private.h @@ -33,7 +33,8 @@ G_BEGIN_DECLS GNode *as_app_node_insert (AsApp *app, - GNode *parent); + GNode *parent, + gdouble api_version); gboolean as_app_node_parse (AsApp *app, GNode *node, GError **error); diff --git a/libappstream-glib/as-app.c b/libappstream-glib/as-app.c index 660d182..209736d 100644 --- a/libappstream-glib/as-app.c +++ b/libappstream-glib/as-app.c @@ -1159,6 +1159,7 @@ as_app_node_insert_languages (AsApp *app, GNode *parent) * as_app_node_insert: (skip) * @app: a #AsApp instance. * @parent: the parent #GNode to use.. + * @api_version: the AppStream API version * * Inserts the application into the DOM tree. * @@ -1167,7 +1168,7 @@ as_app_node_insert_languages (AsApp *app, GNode *parent) * Since: 0.1.0 **/ GNode * -as_app_node_insert (AsApp *app, GNode *parent) +as_app_node_insert (AsApp *app, GNode *parent, gdouble api_version) { AsAppPrivate *priv = GET_PRIVATE (app); AsRelease *rel; @@ -1177,12 +1178,23 @@ as_app_node_insert (AsApp *app, GNode *parent) const gchar *tmp; guint i; - node_app = as_node_insert (parent, "application", NULL, 0, NULL); + /* <component> or <application> */ + if (api_version >= 0.6) { + node_app = as_node_insert (parent, "component", NULL, 0, + "type", as_id_kind_to_string (priv->id_kind), + NULL); + } else { + node_app = as_node_insert (parent, "application", NULL, 0, NULL); + } /* <id> */ - as_node_insert (node_app, "id", priv->id_full, 0, - "type", as_id_kind_to_string (priv->id_kind), - NULL); + node_tmp = as_node_insert (node_app, "id", priv->id_full, 0, NULL); + if (api_version < 0.6) { + as_node_add_attribute (node_tmp, + "type", + as_id_kind_to_string (priv->id_kind), + -1); + } /* <priority> */ if (priv->priority != 0) { @@ -1204,8 +1216,13 @@ as_app_node_insert (AsApp *app, GNode *parent) as_node_insert_localized (node_app, "summary", priv->comments, 0); /* <description> */ - as_node_insert_localized (node_app, "description", priv->descriptions, - AS_NODE_INSERT_FLAG_PRE_ESCAPED); + if (api_version < 0.6) { + as_node_insert_localized (node_app, "description", priv->descriptions, + AS_NODE_INSERT_FLAG_NO_MARKUP); + } else { + as_node_insert_localized (node_app, "description", priv->descriptions, + AS_NODE_INSERT_FLAG_PRE_ESCAPED); + } /* <icon> */ if (priv->icon != NULL) { @@ -1215,16 +1232,26 @@ as_app_node_insert (AsApp *app, GNode *parent) } /* <categories> */ - if (priv->categories->len > 0) { - node_tmp = as_node_insert (node_app, "categories", NULL, 0, NULL); - for (i = 0; i < priv->categories->len; i++) { - tmp = g_ptr_array_index (priv->categories, i); - as_node_insert (node_tmp, "category", tmp, 0, NULL); + if (api_version >= 0.5) { + if (priv->categories->len > 0) { + node_tmp = as_node_insert (node_app, "categories", NULL, 0, NULL); + for (i = 0; i < priv->categories->len; i++) { + tmp = g_ptr_array_index (priv->categories, i); + as_node_insert (node_tmp, "category", tmp, 0, NULL); + } + } + } else { + if (priv->categories->len > 0) { + node_tmp = as_node_insert (node_app, "appcategories", NULL, 0, NULL); + for (i = 0; i < priv->categories->len; i++) { + tmp = g_ptr_array_index (priv->categories, i); + as_node_insert (node_tmp, "appcategory", tmp, 0, NULL); + } } } /* <architectures> */ - if (priv->categories->len > 0) { + if (priv->architectures->len > 0 && api_version >= 0.6) { node_tmp = as_node_insert (node_app, "architectures", NULL, 0, NULL); for (i = 0; i < priv->architectures->len; i++) { tmp = g_ptr_array_index (priv->architectures, i); @@ -1250,23 +1277,28 @@ as_app_node_insert (AsApp *app, GNode *parent) } } - /* <project_license> */ + /* <project_license> or <licence> */ if (priv->project_license != NULL) { - as_node_insert (node_app, "project_license", - priv->project_license, 0, NULL); + if (api_version >= 0.4) { + as_node_insert (node_app, "project_license", + priv->project_license, 0, NULL); + } else { + as_node_insert (node_app, "licence", + priv->project_license, 0, NULL); + } } /* <url> */ as_node_insert_hash (node_app, "url", "type", priv->urls, 0); /* <project_group> */ - if (priv->project_group != NULL) { + if (priv->project_group != NULL && api_version >= 0.4) { as_node_insert (node_app, "project_group", priv->project_group, 0, NULL); } /* <compulsory_for_desktop> */ - if (priv->compulsory_for_desktops != NULL) { + if (priv->compulsory_for_desktops != NULL && api_version >= 0.4) { for (i = 0; i < priv->compulsory_for_desktops->len; i++) { tmp = g_ptr_array_index (priv->compulsory_for_desktops, i); as_node_insert (node_app, "compulsory_for_desktop", @@ -1275,25 +1307,25 @@ as_app_node_insert (AsApp *app, GNode *parent) } /* <screenshots> */ - if (priv->screenshots->len > 0) { + if (priv->screenshots->len > 0 && api_version >= 0.4) { node_tmp = as_node_insert (node_app, "screenshots", NULL, 0, NULL); for (i = 0; i < priv->screenshots->len; i++) { ss = g_ptr_array_index (priv->screenshots, i); - as_screenshot_node_insert (ss, node_tmp); + as_screenshot_node_insert (ss, node_tmp, api_version); } } /* <releases> */ - if (priv->releases->len > 0) { + if (priv->releases->len > 0 && api_version >= 0.6) { node_tmp = as_node_insert (node_app, "releases", NULL, 0, NULL); for (i = 0; i < priv->releases->len && i < 3; i++) { rel = g_ptr_array_index (priv->releases, i); - as_release_node_insert (rel, node_tmp); + as_release_node_insert (rel, node_tmp, api_version); } } /* <languages> */ - if (g_hash_table_size (priv->languages) > 0) + if (g_hash_table_size (priv->languages) > 0 && api_version >= 0.4) as_app_node_insert_languages (app, node_app); /* <metadata> */ @@ -1327,7 +1359,8 @@ as_app_node_parse_child (AsApp *app, GNode *n, GError **error) /* <id> */ case AS_TAG_ID: tmp = as_node_get_attribute (n, "type"); - as_app_set_id_kind (app, as_id_kind_from_string (tmp)); + if (tmp != NULL) + as_app_set_id_kind (app, as_id_kind_from_string (tmp)); as_app_set_id_full (app, as_node_get_data (n), -1); break; @@ -1391,7 +1424,8 @@ as_app_node_parse_child (AsApp *app, GNode *n, GError **error) case AS_TAG_CATEGORIES: g_ptr_array_set_size (priv->categories, 0); for (c = n->children; c != NULL; c = c->next) { - if (g_strcmp0 (as_node_get_name (c), "category") != 0) + if (g_strcmp0 (as_node_get_name (c), "category") != 0 && + g_strcmp0 (as_node_get_name (c), "appcategory") != 0) continue; g_ptr_array_add (priv->categories, as_node_take_data (c)); } @@ -1540,8 +1574,16 @@ as_app_node_parse (AsApp *app, GNode *node, GError **error) { AsAppPrivate *priv = GET_PRIVATE (app); GNode *n; + const gchar *tmp; gboolean ret = TRUE; + /* new style */ + if (g_strcmp0 (as_node_get_name (node), "component") == 0) { + tmp = as_node_get_attribute (node, "type"); + if (tmp != NULL) + as_app_set_id_kind (app, as_id_kind_from_string (tmp)); + } + /* parse each node */ g_ptr_array_set_size (priv->compulsory_for_desktops, 0); g_ptr_array_set_size (priv->pkgnames, 0); diff --git a/libappstream-glib/as-image-private.h b/libappstream-glib/as-image-private.h index d3098f8..2381f1e 100644 --- a/libappstream-glib/as-image-private.h +++ b/libappstream-glib/as-image-private.h @@ -31,7 +31,8 @@ G_BEGIN_DECLS GNode *as_image_node_insert (AsImage *image, - GNode *parent); + GNode *parent, + gdouble api_version); gboolean as_image_node_parse (AsImage *image, GNode *node, GError **error); diff --git a/libappstream-glib/as-image.c b/libappstream-glib/as-image.c index 9079269..e18eee7 100644 --- a/libappstream-glib/as-image.c +++ b/libappstream-glib/as-image.c @@ -262,6 +262,7 @@ as_image_set_kind (AsImage *image, AsImageKind kind) * as_image_node_insert: (skip) * @image: a #AsImage instance. * @parent: the parent #GNode to use.. + * @api_version: the AppStream API version * * Inserts the image into the DOM tree. * @@ -270,7 +271,7 @@ as_image_set_kind (AsImage *image, AsImageKind kind) * Since: 0.1.0 **/ GNode * -as_image_node_insert (AsImage *image, GNode *parent) +as_image_node_insert (AsImage *image, GNode *parent, gdouble api_version) { AsImagePrivate *priv = GET_PRIVATE (image); GNode *n; diff --git a/libappstream-glib/as-node.c b/libappstream-glib/as-node.c index 9f8e3f8..1b818c3 100644 --- a/libappstream-glib/as-node.c +++ b/libappstream-glib/as-node.c @@ -955,8 +955,13 @@ as_node_insert_localized (GNode *parent, value = g_hash_table_lookup (localized, key); data = g_slice_new (AsNodeData); data->name = g_strdup (name); - data->cdata = g_strdup (value); - data->cdata_escaped = insert_flags & AS_NODE_INSERT_FLAG_PRE_ESCAPED; + if (insert_flags & AS_NODE_INSERT_FLAG_NO_MARKUP) { + data->cdata = as_markup_convert_simple (value, -1, NULL); + data->cdata_escaped = FALSE; + } else { + data->cdata = g_strdup (value); + data->cdata_escaped = insert_flags & AS_NODE_INSERT_FLAG_PRE_ESCAPED; + } data->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, diff --git a/libappstream-glib/as-node.h b/libappstream-glib/as-node.h index 71b7cf6..44562bb 100644 --- a/libappstream-glib/as-node.h +++ b/libappstream-glib/as-node.h @@ -67,6 +67,7 @@ typedef enum { * @AS_NODE_INSERT_FLAG_NONE: No extra flags to use * @AS_NODE_INSERT_FLAG_PRE_ESCAPED: The data is already XML escaped * @AS_NODE_INSERT_FLAG_SWAPPED: The name and key should be swapped + * @AS_NODE_INSERT_FLAG_NO_MARKUP: Preformat the 'description' markup * * The flags to use when inserting a node. **/ @@ -74,6 +75,7 @@ typedef enum { AS_NODE_INSERT_FLAG_NONE = 0, /* Since: 0.1.0 */ AS_NODE_INSERT_FLAG_PRE_ESCAPED = 1, /* Since: 0.1.0 */ AS_NODE_INSERT_FLAG_SWAPPED = 2, /* Since: 0.1.0 */ + AS_NODE_INSERT_FLAG_NO_MARKUP = 4, /* Since: 0.1.1 */ /*< private >*/ AS_NODE_INSERT_FLAG_LAST } AsNodeInsertFlags; diff --git a/libappstream-glib/as-release-private.h b/libappstream-glib/as-release-private.h index 3b0717e..73654c6 100644 --- a/libappstream-glib/as-release-private.h +++ b/libappstream-glib/as-release-private.h @@ -31,7 +31,8 @@ G_BEGIN_DECLS GNode *as_release_node_insert (AsRelease *release, - GNode *parent); + GNode *parent, + gdouble api_version); gboolean as_release_node_parse (AsRelease *release, GNode *node, GError **error); diff --git a/libappstream-glib/as-release.c b/libappstream-glib/as-release.c index a19d327..635b192 100644 --- a/libappstream-glib/as-release.c +++ b/libappstream-glib/as-release.c @@ -214,15 +214,16 @@ as_release_set_description (AsRelease *release, * as_release_node_insert: (skip) * @release: a #AsRelease instance. * @parent: the parent #GNode to use.. + * @api_version: the AppStream API version * * Inserts the release into the DOM tree. * * Returns: (transfer full): A populated #GNode * - * Since: 0.1.0 + * Since: 0.1.1 **/ GNode * -as_release_node_insert (AsRelease *release, GNode *parent) +as_release_node_insert (AsRelease *release, GNode *parent, gdouble api_version) { AsReleasePrivate *priv = GET_PRIVATE (release); GNode *n; @@ -235,7 +236,7 @@ as_release_node_insert (AsRelease *release, GNode *parent) "timestamp", timestamp_str, "version", priv->version, NULL); - if (priv->descriptions != NULL) { + if (priv->descriptions != NULL && api_version >= 0.6) { as_node_insert_localized (n, "description", priv->descriptions, AS_NODE_INSERT_FLAG_PRE_ESCAPED); } diff --git a/libappstream-glib/as-screenshot-private.h b/libappstream-glib/as-screenshot-private.h index 2e25c80..92ccaa9 100644 --- a/libappstream-glib/as-screenshot-private.h +++ b/libappstream-glib/as-screenshot-private.h @@ -33,7 +33,8 @@ G_BEGIN_DECLS GNode *as_screenshot_node_insert (AsScreenshot *screenshot, - GNode *parent); + GNode *parent, + gdouble api_version); gboolean as_screenshot_node_parse (AsScreenshot *screenshot, GNode *node, GError **error); diff --git a/libappstream-glib/as-screenshot.c b/libappstream-glib/as-screenshot.c index 9ee31f5..05b04a1 100644 --- a/libappstream-glib/as-screenshot.c +++ b/libappstream-glib/as-screenshot.c @@ -242,15 +242,18 @@ as_screenshot_set_caption (AsScreenshot *screenshot, * as_screenshot_node_insert: (skip) * @screenshot: a #AsScreenshot instance. * @parent: the parent #GNode to use.. + * @api_version: the AppStream API version * * Inserts the screenshot into the DOM tree. * * Returns: (transfer full): A populated #GNode * - * Since: 0.1.0 + * Since: 0.1.1 **/ GNode * -as_screenshot_node_insert (AsScreenshot *screenshot, GNode *parent) +as_screenshot_node_insert (AsScreenshot *screenshot, + GNode *parent, + gdouble api_version) { AsImage *image; AsScreenshotPrivate *priv = GET_PRIVATE (screenshot); @@ -261,10 +264,11 @@ as_screenshot_node_insert (AsScreenshot *screenshot, GNode *parent) AS_NODE_INSERT_FLAG_NONE, "type", as_screenshot_kind_to_string (priv->kind), NULL); - as_node_insert_localized (n, "caption", priv->captions, 0); + if (api_version >= 0.5) + as_node_insert_localized (n, "caption", priv->captions, 0); for (i = 0; i < priv->images->len; i++) { image = g_ptr_array_index (priv->images, i); - as_image_node_insert (image, n); + as_image_node_insert (image, n, api_version); } return n; } diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c index fbe8a1b..aff098e 100644 --- a/libappstream-glib/as-self-test.c +++ b/libappstream-glib/as-self-test.c @@ -104,7 +104,7 @@ ch_test_release_func (void) /* back to node */ root = as_node_new (); - n = as_release_node_insert (release, root); + n = as_release_node_insert (release, root, 0.4); xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE); g_assert_cmpstr (xml->str, ==, src); g_string_free (xml, TRUE); @@ -149,7 +149,7 @@ ch_test_release_desc_func (void) /* back to node */ root = as_node_new (); - n = as_release_node_insert (release, root); + n = as_release_node_insert (release, root, 0.6); xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE); g_assert_cmpstr (xml->str, ==, src); g_string_free (xml, TRUE); @@ -192,7 +192,7 @@ ch_test_image_func (void) /* back to node */ root = as_node_new (); - n = as_image_node_insert (image, root); + n = as_image_node_insert (image, root, 0.4); xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE); g_assert_cmpstr (xml->str, ==, src); g_string_free (xml, TRUE); @@ -239,7 +239,7 @@ ch_test_screenshot_func (void) /* back to node */ root = as_node_new (); - n = as_screenshot_node_insert (screenshot, root); + n = as_screenshot_node_insert (screenshot, root, 0.6); xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE); g_assert_cmpstr (xml->str, ==, src); g_string_free (xml, TRUE); @@ -258,8 +258,8 @@ ch_test_app_func (void) GString *xml; gboolean ret; const gchar *src = - "<application>" - "<id type=\"desktop\">org.gnome.Software.desktop</id>" + "<component type=\"desktop\">" + "<id>org.gnome.Software.desktop</id>" "<priority>-4</priority>" "<pkgname>gnome-software</pkgname>" "<name>Software</name>" @@ -296,7 +296,7 @@ ch_test_app_func (void) "<metadata>" "<value key=\"X-Kudo-GTK3\"/>" "</metadata>" - "</application>"; + "</component>"; app = as_app_new (); @@ -304,7 +304,7 @@ ch_test_app_func (void) root = as_node_from_xml (src, -1, 0, &error); g_assert_no_error (error); g_assert (root != NULL); - n = as_node_find (root, "application"); + n = as_node_find (root, "component"); g_assert (n != NULL); ret = as_app_node_parse (app, n, &error); g_assert_no_error (error); @@ -327,7 +327,7 @@ ch_test_app_func (void) /* back to node */ root = as_node_new (); - n = as_app_node_insert (app, root); + n = as_app_node_insert (app, root, 0.6); xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE); g_assert_cmpstr (xml->str, ==, src); g_string_free (xml, TRUE); @@ -370,7 +370,7 @@ ch_test_app_no_markup_func (void) /* back to node */ root = as_node_new (); - n = as_app_node_insert (app, root); + n = as_app_node_insert (app, root, 0.4); xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE); g_assert_cmpstr (xml->str, ==, src); g_string_free (xml, TRUE); @@ -651,6 +651,8 @@ ch_test_store_func (void) /* create a store and add a single app */ store = as_store_new (); + g_assert_cmpfloat (as_store_get_api_version (store), <, 1.f); + g_assert_cmpfloat (as_store_get_api_version (store), >, 0.f); app = as_app_new (); as_app_set_id_full (app, "gnome-software.desktop", -1); as_app_set_id_kind (app, AS_ID_KIND_DESKTOP); @@ -667,6 +669,7 @@ ch_test_store_func (void) as_store_remove_app (store, app); /* check string output */ + as_store_set_api_version (store, 0.4); xml = as_store_to_xml (store, 0); g_assert_cmpstr (xml->str, ==, "<applications version=\"0.4\">" @@ -679,6 +682,92 @@ ch_test_store_func (void) } static void +ch_test_store_versions_func (void) +{ + AsStore *store; + GError *error = NULL; + gboolean ret; + GString *str; + + /* load a file to the store */ + store = as_store_new (); + ret = as_store_from_xml (store, + "<applications version=\"0.4\">" + "<application>" + "<id type=\"desktop\">test.desktop</id>" + "<description><p>Hello world</p></description>" + "<architectures><arch>i386</arch></architectures>" + "<releases>" + "<release version=\"0.1.2\" timestamp=\"123\">" + "<description><p>Hello</p></description>" + "</release>" + "</releases>" + "</application>" + "</applications>", -1, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + g_assert_cmpfloat (as_store_get_api_version (store), <, 0.4 + 0.01); + g_assert_cmpfloat (as_store_get_api_version (store), >, 0.4 - 0.01); + + /* test with latest features */ + as_store_set_api_version (store, 0.6); + g_assert_cmpfloat (as_store_get_api_version (store), <, 0.6 + 0.01); + g_assert_cmpfloat (as_store_get_api_version (store), >, 0.6 - 0.01); + str = as_store_to_xml (store, 0); + g_assert_cmpstr (str->str, ==, + "<components version=\"0.6\">" + "<component type=\"desktop\">" + "<id>test.desktop</id>" + "<description><p>Hello world</p></description>" + "<architectures><arch>i386</arch></architectures>" + "<releases>" + "<release version=\"0.1.2\" timestamp=\"123\">" + "<description><p>Hello</p></description>" + "</release>" + "</releases>" + "</component>" + "</components>"); + g_string_free (str, TRUE); + + /* test with legacy options */ + as_store_set_api_version (store, 0.3); + str = as_store_to_xml (store, 0); + g_assert_cmpstr (str->str, ==, + "<applications version=\"0.3\">" + "<application>" + "<id type=\"desktop\">test.desktop</id>" + "<description>Hello world</description>" + "</application>" + "</applications>"); + g_string_free (str, TRUE); + + g_object_unref (store); + + /* load a version 0.6 file to the store */ + store = as_store_new (); + ret = as_store_from_xml (store, + "<components version=\"0.6\">" + "<component type=\"desktop\">" + "<id>test.desktop</id>" + "</component>" + "</components>", -1, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* test latest spec version */ + str = as_store_to_xml (store, 0); + g_assert_cmpstr (str->str, ==, + "<components version=\"0.6\">" + "<component type=\"desktop\">" + "<id>test.desktop</id>" + "</component>" + "</components>"); + g_string_free (str, TRUE); + + g_object_unref (store); +} + +static void ch_test_store_origin_func (void) { AsApp *app; @@ -810,6 +899,7 @@ main (int argc, char **argv) g_test_add_func ("/AppStream/node{localized-wrap}", ch_test_node_localized_wrap_func); g_test_add_func ("/AppStream/utils", ch_test_utils_func); g_test_add_func ("/AppStream/store", ch_test_store_func); + g_test_add_func ("/AppStream/store{versions}", ch_test_store_versions_func); g_test_add_func ("/AppStream/store{origin}", ch_test_store_origin_func); g_test_add_func ("/AppStream/store{speed}", ch_test_store_speed_func); diff --git a/libappstream-glib/as-store.c b/libappstream-glib/as-store.c index a0aba05..03820b0 100644 --- a/libappstream-glib/as-store.c +++ b/libappstream-glib/as-store.c @@ -39,11 +39,15 @@ #include "as-app-private.h" #include "as-node-private.h" #include "as-store.h" +#include "as-utils-private.h" + +#define AS_API_VERSION_NEWEST 0.6 typedef struct _AsStorePrivate AsStorePrivate; struct _AsStorePrivate { gchar *origin; + gdouble api_version; GPtrArray *array; /* of AsApp */ GHashTable *hash_id; /* of AsApp{id} */ GHashTable *hash_pkgname; /* of AsApp{pkgname} */ @@ -77,6 +81,7 @@ static void as_store_init (AsStore *store) { AsStorePrivate *priv = GET_PRIVATE (store); + priv->api_version = AS_API_VERSION_NEWEST; priv->array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); priv->hash_id = g_hash_table_new_full (g_str_hash, g_str_equal, @@ -433,17 +438,30 @@ as_store_to_xml (AsStore *store, AsNodeToXmlFlags flags) GNode *node_root; GString *xml; guint i; + gchar version[6]; /* get XML text */ node_root = as_node_new (); - node_apps = as_node_insert (node_root, "applications", NULL, 0, - "version", "0.4", - NULL); + if (priv->api_version >= 0.6) { + node_apps = as_node_insert (node_root, "components", NULL, 0, NULL); + } else { + node_apps = as_node_insert (node_root, "applications", NULL, 0, NULL); + } + + /* set origin attribute */ if (priv->origin != NULL) - as_node_add_attribute (node_root, "origin", priv->origin, -1); + as_node_add_attribute (node_apps, "origin", priv->origin, -1); + + /* set version attribute */ + if (priv->api_version > 0.1f) { + g_ascii_formatd (version, sizeof (version), + "%.1f", priv->api_version); + as_node_add_attribute (node_apps, "version", version, -1); + } + for (i = 0; i < priv->array->len; i++) { app = g_ptr_array_index (priv->array, i); - as_app_node_insert (app, node_apps); + as_app_node_insert (app, node_apps, priv->api_version); } xml = as_node_to_xml (node_root, flags); as_node_unref (node_root); @@ -545,6 +563,39 @@ as_store_set_origin (AsStore *store, const gchar *origin) } /** + * as_store_get_api_version: + * @store: a #AsStore instance. + * + * Gets the AppStream API version. + * + * Returns: the #AsNodeInsertFlags, or 0 if unset + * + * Since: 0.1.1 + **/ +gdouble +as_store_get_api_version (AsStore *store) +{ + AsStorePrivate *priv = GET_PRIVATE (store); + return priv->api_version; +} + +/** + * as_store_set_api_version: + * @store: a #AsStore instance. + * @api_version: the API version + * + * Sets the AppStream API version. + * + * Since: 0.1.1 + **/ +void +as_store_set_api_version (AsStore *store, gdouble api_version) +{ + AsStorePrivate *priv = GET_PRIVATE (store); + priv->api_version = api_version; +} + +/** * as_store_new: * * Creates a new #AsStore. diff --git a/libappstream-glib/as-store.h b/libappstream-glib/as-store.h index 57926a1..54e1c52 100644 --- a/libappstream-glib/as-store.h +++ b/libappstream-glib/as-store.h @@ -99,6 +99,9 @@ gboolean as_store_to_file (AsStore *store, const gchar *as_store_get_origin (AsStore *store); void as_store_set_origin (AsStore *store, const gchar *origin); +gdouble as_store_get_api_version (AsStore *store); +void as_store_set_api_version (AsStore *store, + gdouble api_version); G_END_DECLS diff --git a/libappstream-glib/as-tag.c b/libappstream-glib/as-tag.c index cf5d22c..96b0a86 100644 --- a/libappstream-glib/as-tag.c +++ b/libappstream-glib/as-tag.c @@ -70,6 +70,10 @@ as_tag_from_string (const gchar *tag) return AS_TAG_CATEGORY; if (g_strcmp0 (tag, "licence") == 0) return AS_TAG_PROJECT_LICENSE; + if (g_strcmp0 (tag, "applications") == 0) + return AS_TAG_APPLICATIONS; + if (g_strcmp0 (tag, "application") == 0) + return AS_TAG_APPLICATION; return AS_TAG_UNKNOWN; } @@ -89,8 +93,8 @@ as_tag_to_string (AsTag tag) { const gchar *str[] = { "unknown", - "applications", - "application", + "components", + "component", "id", "pkgname", "name", |