diff options
author | Richard Hughes <richard@hughsie.com> | 2018-04-29 19:18:58 +0100 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2018-04-30 10:22:44 +0100 |
commit | 0f9a78d8dc53cb7b918c4543c957d243bcd67c85 (patch) | |
tree | ddd63ad6de4a4a2503853f97c3b0bee30c9ec03e | |
parent | 261a84db24e28b26a3a5907c5a5c585a666d7c65 (diff) | |
download | appstream-glib-0f9a78d8dc53cb7b918c4543c957d243bcd67c85.tar.gz |
Follow the Debian tilde usage when ordering versions
Debian requires a custom version of strcmp for the version comparison where
tilde is apparently the worst-of-the-worst when checking version segments.
Fixes https://github.com/hughsie/appstream-glib/issues/234
-rw-r--r-- | libappstream-glib/as-self-test.c | 6 | ||||
-rw-r--r-- | libappstream-glib/as-utils.c | 29 |
2 files changed, 32 insertions, 3 deletions
diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c index 3c85a12..c7b4832 100644 --- a/libappstream-glib/as-self-test.c +++ b/libappstream-glib/as-self-test.c @@ -5102,6 +5102,12 @@ as_test_utils_vercmp_func (void) g_assert_cmpint (as_utils_vercmp ("1.2a.3", "1.2b.3"), <, 0); g_assert_cmpint (as_utils_vercmp ("1.2b.3", "1.2a.3"), >, 0); + /* tilde is all-powerful */ + g_assert_cmpint (as_utils_vercmp ("1.2.3~rc1", "1.2.3~rc1"), ==, 0); + g_assert_cmpint (as_utils_vercmp ("1.2.3~rc1", "1.2.3"), <, 0); + g_assert_cmpint (as_utils_vercmp ("1.2.3", "1.2.3~rc1"), >, 0); + g_assert_cmpint (as_utils_vercmp ("1.2.3~rc2", "1.2.3~rc1"), >, 0); + /* invalid */ g_assert_cmpint (as_utils_vercmp ("1", NULL), ==, G_MAXINT); g_assert_cmpint (as_utils_vercmp (NULL, "1"), ==, G_MAXINT); diff --git a/libappstream-glib/as-utils.c b/libappstream-glib/as-utils.c index c605cd1..4a40308 100644 --- a/libappstream-glib/as-utils.c +++ b/libappstream-glib/as-utils.c @@ -1353,13 +1353,36 @@ as_utils_search_tokenize (const gchar *search) return values; } +static gint +as_utils_vercmp_char (gchar chr1, gchar chr2) +{ + if (chr1 == chr2) + return 0; + if (chr1 == '~') + return -1; + if (chr2 == '~') + return 1; + return chr1 < chr2 ? -1 : 1; +} + +static gint +as_utils_vercmp_chunk (const gchar *str1, const gchar *str2) +{ + guint i; + for (i = 0; str1[i] != '\0' && str2[i] != '\0'; i++) { + gint rc = as_utils_vercmp_char (str1[i], str2[i]); + if (rc != 0) + return rc; + } + return as_utils_vercmp_char (str1[i], str2[i]); +} + /** * as_utils_vercmp: * @version_a: the release version, e.g. 1.2.3 * @version_b: the release version, e.g. 1.2.3.1 * - * Compares version numbers for sorting. This function cannot deal with version - * strings that do not contain numbers, for instance "rev2706" or "1.2_alpha". + * Compares version numbers for sorting. * * Returns: -1 if a < b, +1 if a > b, 0 if they are equal, and %G_MAXINT on error * @@ -1411,7 +1434,7 @@ as_utils_vercmp (const gchar *version_a, const gchar *version_b) /* compare strings */ if ((endptr_a != NULL && endptr_a[0] != '\0') || (endptr_b != NULL && endptr_b[0] != '\0')) { - gint rc = g_strcmp0 (endptr_a, endptr_b); + gint rc = as_utils_vercmp_chunk (endptr_a, endptr_b); if (rc < 0) return -1; if (rc > 0) |