Try harder to convert to a version into a correct semver

This is really useful for the flashrom plugin.
This commit is contained in:
Richard Hughes 2022-02-11 09:35:28 +00:00
parent ad0b274cec
commit 55bd4862d3
5 changed files with 105 additions and 1 deletions

View File

@ -235,6 +235,73 @@ _g_ascii_is_digits(const gchar *str)
return TRUE;
}
static guint
fwupd_version_format_number_sections(FwupdVersionFormat fmt)
{
if (fmt == FWUPD_VERSION_FORMAT_PLAIN || fmt == FWUPD_VERSION_FORMAT_NUMBER ||
fmt == FWUPD_VERSION_FORMAT_HEX)
return 1;
if (fmt == FWUPD_VERSION_FORMAT_PAIR || fmt == FWUPD_VERSION_FORMAT_BCD)
return 2;
if (fmt == FWUPD_VERSION_FORMAT_TRIPLET || fmt == FWUPD_VERSION_FORMAT_SURFACE_LEGACY ||
fmt == FWUPD_VERSION_FORMAT_SURFACE || fmt == FWUPD_VERSION_FORMAT_DELL_BIOS)
return 3;
if (fmt == FWUPD_VERSION_FORMAT_QUAD || fmt == FWUPD_VERSION_FORMAT_INTEL_ME ||
fmt == FWUPD_VERSION_FORMAT_INTEL_ME2)
return 4;
return 0;
}
/**
* fu_common_version_ensure_semver_full:
* @version: (nullable): a version number, e.g. ` V1.2.3 `
* @fmt: a version format, e.g. %FWUPD_VERSION_FORMAT_TRIPLET
*
* Builds a semver from the possibly crazy version number. Depending on the @semver value
* the string will be split and a string in the correct format will be returned.
*
* Returns: a version number, e.g. `1.2.3`, or %NULL if the version was not valid
*
* Since: 1.7.6
*/
gchar *
fu_common_version_ensure_semver_full(const gchar *version, FwupdVersionFormat fmt)
{
guint sections_actual;
guint sections_expected = fwupd_version_format_number_sections(fmt);
g_autofree gchar *tmp = NULL;
g_auto(GStrv) split = NULL;
g_autoptr(GString) str = g_string_new(NULL);
/* split into all sections */
tmp = fu_common_version_ensure_semver(version);
if (tmp == NULL)
return NULL;
if (fmt == FWUPD_VERSION_FORMAT_UNKNOWN)
return g_steal_pointer(&tmp);
split = g_strsplit(tmp, ".", -1);
sections_actual = g_strv_length(split);
/* add zero sections as required */
if (sections_actual < sections_expected) {
for (guint i = 0; i < sections_expected - sections_actual; i++) {
if (str->len > 0)
g_string_append(str, ".");
g_string_append(str, "0");
}
}
/* only add enough sections for the format */
for (guint i = 0; i < sections_actual && i < sections_expected; i++) {
if (str->len > 0)
g_string_append(str, ".");
g_string_append(str, split[i]);
}
/* success */
return g_string_free(g_steal_pointer(&str), FALSE);
}
/**
* fu_common_version_ensure_semver:
* @version: (nullable): a version number, e.g. ` V1.2.3 `
@ -281,6 +348,10 @@ fu_common_version_ensure_semver(const gchar *version)
}
}
/* remove any trailing dot */
if (version_safe->len > 0 && version_safe->str[version_safe->len - 1] == '.')
g_string_truncate(version_safe, version_safe->len - 1);
/* found no digits */
if (digit_cnt == 0)
return NULL;

View File

@ -21,6 +21,8 @@ gchar *
fu_common_version_parse_from_format(const gchar *version, FwupdVersionFormat fmt);
gchar *
fu_common_version_ensure_semver(const gchar *version);
gchar *
fu_common_version_ensure_semver_full(const gchar *version, FwupdVersionFormat fmt);
FwupdVersionFormat
fu_common_version_guess_format(const gchar *version);
gboolean

View File

@ -2411,7 +2411,9 @@ fu_device_set_version(FuDevice *self, const gchar *version)
/* sanitize if required */
if (fu_device_has_internal_flag(self, FU_DEVICE_INTERNAL_FLAG_ENSURE_SEMVER)) {
version_safe = fu_common_version_ensure_semver(version);
version_safe =
fu_common_version_ensure_semver_full(version,
fu_device_get_version_format(self));
if (g_strcmp0(version, version_safe) != 0)
g_debug("converted '%s' to '%s'", version, version_safe);
} else {

View File

@ -2203,6 +2203,28 @@ fu_common_version_semver_func(void)
}
}
static void
fu_common_version_semver_full_func(void)
{
struct {
const gchar *old;
const gchar *new;
FwupdVersionFormat fmt;
} map[] = {{"1.2.3", "1.2.3", FWUPD_VERSION_FORMAT_TRIPLET},
{"1.2.3.4", "1.2.3", FWUPD_VERSION_FORMAT_TRIPLET},
{"1.2", "0.1.2", FWUPD_VERSION_FORMAT_TRIPLET},
{"1", "0.0.1", FWUPD_VERSION_FORMAT_TRIPLET},
{"CBET1.2.3", "1.2.3", FWUPD_VERSION_FORMAT_TRIPLET},
{"4.11-1190-g12d8072e6b-dirty", "4.11.1190", FWUPD_VERSION_FORMAT_TRIPLET},
{"4.11-1190-g12d8072e6b-dirty", "4.11", FWUPD_VERSION_FORMAT_PAIR},
{NULL, NULL}};
for (guint i = 0; map[i].old != NULL; i++) {
g_autofree gchar *tmp =
fu_common_version_ensure_semver_full(map[i].old, map[i].fmt);
g_assert_cmpstr(tmp, ==, map[i].new);
}
}
static void
fu_common_strtoull_func(void)
{
@ -3944,6 +3966,7 @@ main(int argc, char **argv)
g_test_add_func("/fwupd/common{strtoull}", fu_common_strtoull_func);
g_test_add_func("/fwupd/common{version}", fu_common_version_func);
g_test_add_func("/fwupd/common{version-semver}", fu_common_version_semver_func);
g_test_add_func("/fwupd/common{version-semver-full}", fu_common_version_semver_full_func);
g_test_add_func("/fwupd/common{vercmp}", fu_common_vercmp_func);
g_test_add_func("/fwupd/common{strstrip}", fu_common_strstrip_func);
g_test_add_func("/fwupd/common{endian}", fu_common_endian_func);

View File

@ -995,3 +995,9 @@ LIBFWUPDPLUGIN_1.7.4 {
fu_usb_device_set_configuration;
local: *;
} LIBFWUPDPLUGIN_1.7.3;
LIBFWUPDPLUGIN_1.7.6 {
global:
fu_common_version_ensure_semver_full;
local: *;
} LIBFWUPDPLUGIN_1.7.4;