Consider the release priority when returning results

This means we might be able to offer two versions of firmware for the same
device, where one has additional requirement such as a CHID.

The idea here is to allow OEMs to distribute thier own superset dbx updates on
the LVFS without having to invent an anti-CHID requirement type.
This commit is contained in:
Richard Hughes 2022-10-17 16:27:43 +01:00
parent 31f481518b
commit 1c35757f85
4 changed files with 50 additions and 18 deletions

View File

@ -5052,19 +5052,24 @@ static gint
fu_engine_sort_releases_cb(gconstpointer a, gconstpointer b, gpointer user_data)
{
FuDevice *device = FU_DEVICE(user_data);
FwupdRelease *rel_a = FWUPD_RELEASE(*((FwupdRelease **)a));
FwupdRelease *rel_b = FWUPD_RELEASE(*((FwupdRelease **)b));
FuRelease *rel_a = FU_RELEASE(*((FuRelease **)a));
FuRelease *rel_b = FU_RELEASE(*((FuRelease **)b));
gint rc;
/* first by branch */
rc = g_strcmp0(fwupd_release_get_branch(rel_b), fwupd_release_get_branch(rel_a));
rc = g_strcmp0(fu_release_get_branch(rel_b), fu_release_get_branch(rel_a));
if (rc != 0)
return rc;
/* then by version */
return fu_version_compare(fwupd_release_get_version(rel_b),
fwupd_release_get_version(rel_a),
fu_device_get_version_format(device));
rc = fu_version_compare(fu_release_get_version(rel_b),
fu_release_get_version(rel_a),
fu_device_get_version_format(device));
if (rc != 0)
return rc;
/* then by priority */
return fu_release_compare(rel_a, rel_b);
}
static gboolean

View File

@ -33,6 +33,7 @@ struct _FuRelease {
gboolean is_downgrade;
GPtrArray *soft_reqs; /* nullable, element-type XbNode */
GPtrArray *hard_reqs; /* nullable, element-type XbNode */
guint64 priority;
};
G_DEFINE_TYPE(FuRelease, fu_release, FWUPD_TYPE_RELEASE)
@ -618,6 +619,13 @@ fu_release_check_requirements(FuRelease *self,
return TRUE;
}
void
fu_release_set_priority(FuRelease *self, guint64 priority)
{
g_return_if_fail(FU_IS_RELEASE(self));
self->priority = priority;
}
/**
* fu_release_load:
* @self: a #FuRelease
@ -689,6 +697,9 @@ fu_release_load(FuRelease *self,
tmp = xb_node_query_text(component, "developer_name", NULL);
if (tmp != NULL)
fwupd_release_set_vendor(FWUPD_RELEASE(self), tmp);
tmp64 = xb_node_get_attr_as_uint(component, "priority");
if (tmp64 != G_MAXUINT64)
fu_release_set_priority(self, tmp64);
/* use default release */
if (rel_optional == NULL) {
@ -1014,7 +1025,7 @@ fu_release_get_action_id(FuRelease *self)
* @release1: first task to compare.
* @release2: second task to compare.
*
* Compares two install tasks.
* Compares two releases.
*
* Returns: 1, 0 or -1 if @release1 is greater, equal, or less than @release2, respectively.
**/
@ -1023,10 +1034,18 @@ fu_release_compare(FuRelease *release1, FuRelease *release2)
{
FuDevice *device1 = fu_release_get_device(release1);
FuDevice *device2 = fu_release_get_device(release2);
/* device order, lower is better */
if (fu_device_get_order(device1) < fu_device_get_order(device2))
return -1;
if (fu_device_get_order(device1) > fu_device_get_order(device2))
return 1;
/* release priority, higher is better */
if (release1->priority > release2->priority)
return -1;
if (release1->priority < release2->priority)
return 1;
return 0;
}

View File

@ -23,6 +23,7 @@ fu_release_new(void);
#define fu_release_add_flag(r, v) fwupd_release_add_flag(FWUPD_RELEASE(r), v)
#define fu_release_add_tag(r, v) fwupd_release_add_tag(FWUPD_RELEASE(r), v)
#define fu_release_add_metadata(r, v) fwupd_release_add_metadata(FWUPD_RELEASE(r), v)
#define fu_release_set_branch(r, v) fwupd_release_set_branch(FWUPD_RELEASE(r), v)
FuDevice *
fu_release_get_device(FuRelease *self);
@ -58,3 +59,5 @@ const gchar *
fu_release_get_action_id(FuRelease *self);
gint
fu_release_compare(FuRelease *release1, FuRelease *release2);
void
fu_release_set_priority(FuRelease *self, guint64 priority);

View File

@ -4096,7 +4096,6 @@ fu_spawn_timeout_func(void)
static void
fu_release_compare_func(gconstpointer user_data)
{
FuDevice *device_tmp;
g_autoptr(GPtrArray) releases = g_ptr_array_new();
g_autoptr(FuDevice) device1 = fu_device_new(NULL);
g_autoptr(FuDevice) device2 = fu_device_new(NULL);
@ -4105,25 +4104,31 @@ fu_release_compare_func(gconstpointer user_data)
g_autoptr(FuRelease) release2 = fu_release_new();
g_autoptr(FuRelease) release3 = fu_release_new();
fu_device_set_order(device1, 99);
fu_device_set_order(device1, 33);
fu_release_set_device(release1, device1);
g_ptr_array_add(releases, release1);
fu_release_set_priority(release1, 0);
fu_release_set_branch(release1, "1");
fu_device_set_order(device2, 11);
fu_release_set_device(release2, device2);
g_ptr_array_add(releases, release2);
fu_device_set_order(device3, 33);
fu_release_set_priority(release2, 0);
fu_release_set_branch(release2, "2");
fu_device_set_order(device3, 11);
fu_release_set_device(release3, device3);
fu_release_set_priority(release3, 99);
fu_release_set_branch(release3, "3");
g_ptr_array_add(releases, release1);
g_ptr_array_add(releases, release2);
g_ptr_array_add(releases, release3);
/* order the install tasks */
g_ptr_array_sort(releases, fu_release_compare_func_cb);
g_assert_cmpint(releases->len, ==, 3);
device_tmp = fu_release_get_device(g_ptr_array_index(releases, 0));
g_assert_cmpint(fu_device_get_order(device_tmp), ==, 11);
device_tmp = fu_release_get_device(g_ptr_array_index(releases, 1));
g_assert_cmpint(fu_device_get_order(device_tmp), ==, 33);
device_tmp = fu_release_get_device(g_ptr_array_index(releases, 2));
g_assert_cmpint(fu_device_get_order(device_tmp), ==, 99);
g_assert_cmpstr(fu_release_get_branch(g_ptr_array_index(releases, 0)), ==, "3");
g_assert_cmpstr(fu_release_get_branch(g_ptr_array_index(releases, 1)), ==, "2");
g_assert_cmpstr(fu_release_get_branch(g_ptr_array_index(releases, 2)), ==, "1");
}
static void