From 6212d2eddc2d424813013be383af92388f54f9d8 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Mon, 28 Dec 2015 08:58:11 +0000 Subject: Fix AppStream generation when using duplicate .deb packages For package types without a native klass->compare fall back to something sensible. Also add some self tests for this to make sure this never happens again. Fixes https://github.com/hughsie/appstream-glib/issues/72 --- libappstream-builder/asb-package.c | 66 ++++++++++++++++++++++++++++++++++-- libappstream-builder/asb-package.h | 2 ++ libappstream-builder/asb-self-test.c | 24 +++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) diff --git a/libappstream-builder/asb-package.c b/libappstream-builder/asb-package.c index 14adaa6..be1cbd8 100644 --- a/libappstream-builder/asb-package.c +++ b/libappstream-builder/asb-package.c @@ -300,6 +300,23 @@ asb_package_get_kind (AsbPackage *pkg) return priv->kind; } +/** + * asb_package_get_epoch: + * @pkg: A #AsbPackage + * + * Gets the epoch of the package. + * + * Returns: a #AsbPackageKind + * + * Since: 0.5.6 + **/ +guint +asb_package_get_epoch (AsbPackage *pkg) +{ + AsbPackagePrivate *priv = GET_PRIVATE (pkg); + return priv->epoch; +} + /** * asb_package_get_basename: * @pkg: A #AsbPackage @@ -351,6 +368,23 @@ asb_package_get_version (AsbPackage *pkg) return priv->version; } +/** + * asb_package_get_release_str: + * @pkg: A #AsbPackage + * + * Gets the package release string + * + * Returns: utf8 string + * + * Since: 0.5.6 + **/ +const gchar * +asb_package_get_release_str (AsbPackage *pkg) +{ + AsbPackagePrivate *priv = GET_PRIVATE (pkg); + return priv->release; +} + /** * asb_package_get_arch: * @pkg: A #AsbPackage @@ -1112,17 +1146,45 @@ asb_package_get_releases (AsbPackage *pkg) * * Compares one package with another. * - * Returns: -1 for <, 0 for the same and +1 for > + * Returns: +1 for @pkg1 newer, 0 for the same and -1 if @pkg2 is newer * * Since: 0.1.0 **/ gint asb_package_compare (AsbPackage *pkg1, AsbPackage *pkg2) { + AsbPackagePrivate *priv1 = GET_PRIVATE (pkg1); + AsbPackagePrivate *priv2 = GET_PRIVATE (pkg2); AsbPackageClass *klass = ASB_PACKAGE_GET_CLASS (pkg1); + gint rc; + + /* class-specific compare method */ if (klass->compare != NULL) return klass->compare (pkg1, pkg2); - return 0; + + /* check name */ + rc = g_strcmp0 (priv1->name, priv2->name); + if (rc != 0) + return rc; + + /* check epoch */ + if (priv1->epoch < priv2->epoch) + return -1; + if (priv1->epoch > priv2->epoch) + return 1; + + /* check version */ + rc = as_utils_vercmp (priv1->version, priv2->version); + if (rc != 0) + return rc; + + /* check release */ + rc = as_utils_vercmp (priv1->release, priv2->release); + if (rc != 0) + return rc; + + /* check arch */ + return g_strcmp0 (priv1->arch, priv2->arch); } /** diff --git a/libappstream-builder/asb-package.h b/libappstream-builder/asb-package.h index cea89b8..8c2e28f 100644 --- a/libappstream-builder/asb-package.h +++ b/libappstream-builder/asb-package.h @@ -110,11 +110,13 @@ gboolean asb_package_explode (AsbPackage *pkg, GPtrArray *glob, GError **error); AsbPackageKind asb_package_get_kind (AsbPackage *pkg); +guint asb_package_get_epoch (AsbPackage *pkg); const gchar *asb_package_get_filename (AsbPackage *pkg); const gchar *asb_package_get_basename (AsbPackage *pkg); const gchar *asb_package_get_arch (AsbPackage *pkg); const gchar *asb_package_get_name (AsbPackage *pkg); const gchar *asb_package_get_version (AsbPackage *pkg); +const gchar *asb_package_get_release_str (AsbPackage *pkg); const gchar *asb_package_get_nevr (AsbPackage *pkg); const gchar *asb_package_get_nevra (AsbPackage *pkg); const gchar *asb_package_get_evr (AsbPackage *pkg); diff --git a/libappstream-builder/asb-self-test.c b/libappstream-builder/asb-self-test.c index 12010c7..91a2f6b 100644 --- a/libappstream-builder/asb-self-test.c +++ b/libappstream-builder/asb-self-test.c @@ -212,12 +212,36 @@ static void asb_test_package_func (void) { g_autoptr(AsbPackage) pkg = NULL; + g_autoptr(AsbPackage) pkg2 = NULL; + + /* set package values from filename */ pkg = asb_package_new (); asb_package_set_filename (pkg, "/tmp/gambit-c-doc-4.7.3-2.fc22.noarch.rpm"); g_assert_cmpstr (asb_package_get_nevra (pkg), ==, "gambit-c-doc-4.7.3-2.fc22.noarch"); g_assert_cmpstr (asb_package_get_name (pkg), ==, "gambit-c-doc"); g_assert_cmpstr (asb_package_get_version (pkg), ==, "4.7.3"); + g_assert_cmpstr (asb_package_get_release_str (pkg), ==, "2.fc22"); g_assert_cmpstr (asb_package_get_arch (pkg), ==, "noarch"); + g_assert_cmpint (asb_package_get_epoch (pkg), ==, 0); + + /* set package values again */ + pkg2 = asb_package_new (); + asb_package_set_filename (pkg2, "/tmp/gambit-c-doc-4.7.3-2.fc22.noarch.rpm"); + + /* check same */ + g_assert_cmpint (asb_package_compare (pkg, pkg2), ==, 0); + + /* fix version */ + asb_package_set_version (pkg2, "4.7.4"); + g_assert_cmpint (asb_package_compare (pkg, pkg2), <, 0); + g_assert_cmpint (asb_package_compare (pkg2, pkg), >, 0); + asb_package_set_version (pkg2, "4.7.3"); + + /* fix release */ + asb_package_set_release (pkg2, "3.fc22"); + g_assert_cmpint (asb_package_compare (pkg, pkg2), <, 0); + g_assert_cmpint (asb_package_compare (pkg2, pkg), >, 0); + asb_package_set_release (pkg2, "2.fc22"); } static void -- cgit v1.2.1