mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-07 17:45:23 +00:00
Add switch-branch support to fwupdtool
This commit is contained in:
parent
0d778dbd50
commit
02f2cc311e
@ -26,6 +26,7 @@ _fwupdtool_cmd_list=(
|
|||||||
'monitor'
|
'monitor'
|
||||||
'reinstall'
|
'reinstall'
|
||||||
'security'
|
'security'
|
||||||
|
'switch-branch'
|
||||||
'self-sign'
|
'self-sign'
|
||||||
'smbios-dump'
|
'smbios-dump'
|
||||||
'attach'
|
'attach'
|
||||||
|
134
src/fu-tool.c
134
src/fu-tool.c
@ -2439,6 +2439,133 @@ fu_util_esp_list (FuUtilPrivate *priv, gchar **values, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_util_switch_branch (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||||
|
{
|
||||||
|
const gchar *branch;
|
||||||
|
g_autoptr(FwupdRelease) rel = NULL;
|
||||||
|
g_autoptr(GPtrArray) rels = NULL;
|
||||||
|
g_autoptr(GPtrArray) branches = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
g_autoptr(FuDevice) dev = NULL;
|
||||||
|
|
||||||
|
/* load engine */
|
||||||
|
if (!fu_util_start_engine (priv, FU_ENGINE_LOAD_FLAG_NONE, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* find the device and check it has multiple branches */
|
||||||
|
priv->filter_include |= FWUPD_DEVICE_FLAG_SUPPORTED;
|
||||||
|
if (g_strv_length (values) == 1)
|
||||||
|
dev = fu_util_get_device (priv, values[1], error);
|
||||||
|
else
|
||||||
|
dev = fu_util_prompt_for_device (priv, NULL, error);
|
||||||
|
if (dev == NULL)
|
||||||
|
return FALSE;
|
||||||
|
if (!fu_device_has_flag (dev, FWUPD_DEVICE_FLAG_HAS_MULTIPLE_BRANCHES)) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOT_SUPPORTED,
|
||||||
|
"Multiple branches not available");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get all releases, including the alternate branch versions */
|
||||||
|
rels = fu_engine_get_releases (priv->engine,
|
||||||
|
priv->request,
|
||||||
|
fu_device_get_id (dev),
|
||||||
|
error);
|
||||||
|
if (rels == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* get all the unique branches */
|
||||||
|
for (guint i = 0; i < rels->len; i++) {
|
||||||
|
FwupdRelease *rel_tmp = g_ptr_array_index (rels, i);
|
||||||
|
const gchar *branch_tmp = fu_util_release_get_branch (rel_tmp);
|
||||||
|
if (g_ptr_array_find_with_equal_func (branches, branch_tmp,
|
||||||
|
g_str_equal, NULL))
|
||||||
|
continue;
|
||||||
|
g_ptr_array_add (branches, g_strdup (branch_tmp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* branch name is optional */
|
||||||
|
if (g_strv_length (values) > 1) {
|
||||||
|
branch = values[1];
|
||||||
|
} else if (branches->len == 1) {
|
||||||
|
branch = g_ptr_array_index (branches, 0);
|
||||||
|
} else {
|
||||||
|
guint idx;
|
||||||
|
|
||||||
|
/* TRANSLATORS: get interactive prompt, where branch is the
|
||||||
|
* supplier of the firmware, e.g. "non-free" or "free" */
|
||||||
|
g_print ("%s\n", _("Choose a branch:"));
|
||||||
|
/* TRANSLATORS: this is to abort the interactive prompt */
|
||||||
|
g_print ("0.\t%s\n", _("Cancel"));
|
||||||
|
for (guint i = 0; i < branches->len; i++) {
|
||||||
|
const gchar *branch_tmp = g_ptr_array_index (branches, i);
|
||||||
|
g_print ("%u.\t%s\n", i + 1, branch_tmp);
|
||||||
|
}
|
||||||
|
idx = fu_util_prompt_for_number (branches->len);
|
||||||
|
if (idx == 0) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOTHING_TO_DO,
|
||||||
|
"Request canceled");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
branch = g_ptr_array_index (branches, idx - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
if (g_strcmp0 (branch, fu_device_get_branch (dev)) == 0) {
|
||||||
|
g_set_error (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOT_SUPPORTED,
|
||||||
|
"Device %s is already on branch %s",
|
||||||
|
fu_device_get_name (dev),
|
||||||
|
branch);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the releases are ordered by version */
|
||||||
|
for (guint j = 0; j < rels->len; j++) {
|
||||||
|
FwupdRelease *rel_tmp = g_ptr_array_index (rels, j);
|
||||||
|
if (g_strcmp0 (fwupd_release_get_branch (rel_tmp), branch) == 0) {
|
||||||
|
rel = g_object_ref (rel_tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rel == NULL) {
|
||||||
|
g_set_error (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOT_SUPPORTED,
|
||||||
|
"No releases for branch %s",
|
||||||
|
branch);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we're switching branch */
|
||||||
|
if (!fu_util_switch_branch_warning (FWUPD_DEVICE (dev), rel, FALSE, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* update the console if composite devices are also updated */
|
||||||
|
priv->current_operation = FU_UTIL_OPERATION_INSTALL;
|
||||||
|
g_signal_connect (priv->engine, "device-changed",
|
||||||
|
G_CALLBACK (fu_util_update_device_changed_cb), priv);
|
||||||
|
priv->flags |= FWUPD_INSTALL_FLAG_ALLOW_REINSTALL;
|
||||||
|
priv->flags |= FWUPD_INSTALL_FLAG_ALLOW_BRANCH_SWITCH;
|
||||||
|
if (!fu_util_install_release (priv, rel, error))
|
||||||
|
return FALSE;
|
||||||
|
fu_util_display_current_message (priv);
|
||||||
|
|
||||||
|
/* we don't want to ask anything */
|
||||||
|
if (priv->no_reboot_check) {
|
||||||
|
g_debug ("skipping reboot check");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fu_util_prompt_complete (priv->completion_flags, TRUE, error);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -2749,6 +2876,12 @@ main (int argc, char *argv[])
|
|||||||
/* TRANSLATORS: command description */
|
/* TRANSLATORS: command description */
|
||||||
_("Lists files on the ESP"),
|
_("Lists files on the ESP"),
|
||||||
fu_util_esp_list);
|
fu_util_esp_list);
|
||||||
|
fu_util_cmd_array_add (cmd_array,
|
||||||
|
"switch-branch",
|
||||||
|
"[DEVICE-ID|GUID] [BRANCH]",
|
||||||
|
/* TRANSLATORS: command description */
|
||||||
|
_("Switch the firmware branch on the device"),
|
||||||
|
fu_util_switch_branch);
|
||||||
|
|
||||||
/* do stuff on ctrl+c */
|
/* do stuff on ctrl+c */
|
||||||
priv->cancellable = g_cancellable_new ();
|
priv->cancellable = g_cancellable_new ();
|
||||||
@ -2772,6 +2905,7 @@ main (int argc, char *argv[])
|
|||||||
/* set our implemented feature set */
|
/* set our implemented feature set */
|
||||||
fu_engine_request_set_feature_flags (priv->request,
|
fu_engine_request_set_feature_flags (priv->request,
|
||||||
FWUPD_FEATURE_FLAG_DETACH_ACTION |
|
FWUPD_FEATURE_FLAG_DETACH_ACTION |
|
||||||
|
FWUPD_FEATURE_FLAG_SWITCH_BRANCH |
|
||||||
FWUPD_FEATURE_FLAG_UPDATE_ACTION);
|
FWUPD_FEATURE_FLAG_UPDATE_ACTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1939,3 +1939,57 @@ fu_util_device_order_sort_cb (gconstpointer a, gconstpointer b)
|
|||||||
FuDevice *device_b = *((FuDevice **) b);
|
FuDevice *device_b = *((FuDevice **) b);
|
||||||
return fu_util_device_order_compare (device_a, device_b);
|
return fu_util_device_order_compare (device_a, device_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
fu_util_switch_branch_warning (FwupdDevice *dev,
|
||||||
|
FwupdRelease *rel,
|
||||||
|
gboolean assume_yes,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
const gchar *desc_markup = NULL;
|
||||||
|
g_autofree gchar *desc_plain = NULL;
|
||||||
|
g_autoptr(GString) desc_full = g_string_new (NULL);
|
||||||
|
|
||||||
|
/* warn the user if the vendor is different */
|
||||||
|
if (g_strcmp0 (fwupd_device_get_vendor (dev), fwupd_release_get_vendor (rel)) != 0) {
|
||||||
|
/* TRANSLATORS: %1 is the firmware vendor, %2 is the device vendor name */
|
||||||
|
g_string_append_printf (desc_full, _("The firmware from %s is not "
|
||||||
|
"supplied by %s, the hardware vendor."),
|
||||||
|
fwupd_release_get_vendor (rel),
|
||||||
|
fwupd_device_get_vendor (dev));
|
||||||
|
g_string_append (desc_full, "\n\n");
|
||||||
|
/* TRANSLATORS: %1 is the device vendor name */
|
||||||
|
g_string_append_printf (desc_full, _("Your hardware may be damaged using this firmware, "
|
||||||
|
"and installing this release may void any warranty "
|
||||||
|
"with %s."),
|
||||||
|
fwupd_device_get_vendor (dev));
|
||||||
|
g_string_append (desc_full, "\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* from the <description> in the AppStream data */
|
||||||
|
desc_markup = fwupd_release_get_description (rel);
|
||||||
|
if (desc_markup == NULL)
|
||||||
|
return TRUE;
|
||||||
|
desc_plain = fu_util_convert_description (desc_markup, error);
|
||||||
|
if (desc_plain == NULL)
|
||||||
|
return FALSE;
|
||||||
|
g_string_append (desc_full, desc_plain);
|
||||||
|
|
||||||
|
/* show and ask user to confirm */
|
||||||
|
fu_util_warning_box (desc_full->str, 80);
|
||||||
|
if (!assume_yes) {
|
||||||
|
/* ask for permission */
|
||||||
|
g_print ("\n%s [y|N]: ",
|
||||||
|
/* TRANSLATORS: should the branch be changed */
|
||||||
|
_("Do you understand the consequences of changing the firmware branch?"));
|
||||||
|
if (!fu_util_prompt_for_boolean (FALSE)) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOTHING_TO_DO,
|
||||||
|
"Declined branch switch");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
@ -113,3 +113,8 @@ gint fu_util_sort_devices_by_flags_cb (gconstpointer a,
|
|||||||
gconstpointer b);
|
gconstpointer b);
|
||||||
gint fu_util_device_order_sort_cb (gconstpointer a,
|
gint fu_util_device_order_sort_cb (gconstpointer a,
|
||||||
gconstpointer b);
|
gconstpointer b);
|
||||||
|
|
||||||
|
gboolean fu_util_switch_branch_warning (FwupdDevice *dev,
|
||||||
|
FwupdRelease *rel,
|
||||||
|
gboolean assume_yes,
|
||||||
|
GError **error);
|
||||||
|
@ -1900,59 +1900,6 @@ fu_util_reinstall (FuUtilPrivate *priv, gchar **values, GError **error)
|
|||||||
return fu_util_prompt_complete (priv->completion_flags, TRUE, error);
|
return fu_util_prompt_complete (priv->completion_flags, TRUE, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fu_util_switch_branch_warning (FuUtilPrivate *priv,
|
|
||||||
FwupdDevice *dev,
|
|
||||||
FwupdRelease *rel,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
const gchar *desc_markup = NULL;
|
|
||||||
g_autofree gchar *desc_plain = NULL;
|
|
||||||
g_autoptr(GString) desc_full = g_string_new (NULL);
|
|
||||||
|
|
||||||
/* warn the user if the vendor is different */
|
|
||||||
if (g_strcmp0 (fwupd_device_get_vendor (dev), fwupd_release_get_vendor (rel)) != 0) {
|
|
||||||
/* TRANSLATORS: %1 is the firmware vendor, %2 is the device vendor name */
|
|
||||||
g_string_append_printf (desc_full, _("The firmware from %s is not "
|
|
||||||
"supplied by %s, the hardware vendor."),
|
|
||||||
fwupd_release_get_vendor (rel),
|
|
||||||
fwupd_device_get_vendor (dev));
|
|
||||||
g_string_append (desc_full, "\n\n");
|
|
||||||
/* TRANSLATORS: %1 is the device vendor name */
|
|
||||||
g_string_append_printf (desc_full, _("Your hardware may be damaged using this firmware, "
|
|
||||||
"and installing this release may void any warranty "
|
|
||||||
"with %s."),
|
|
||||||
fwupd_device_get_vendor (dev));
|
|
||||||
g_string_append (desc_full, "\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* from the <description> in the AppStream data */
|
|
||||||
desc_markup = fwupd_release_get_description (rel);
|
|
||||||
if (desc_markup == NULL)
|
|
||||||
return TRUE;
|
|
||||||
desc_plain = fu_util_convert_description (desc_markup, error);
|
|
||||||
if (desc_plain == NULL)
|
|
||||||
return FALSE;
|
|
||||||
g_string_append (desc_full, desc_plain);
|
|
||||||
|
|
||||||
/* show and ask user to confirm */
|
|
||||||
fu_util_warning_box (desc_full->str, 80);
|
|
||||||
if (!priv->assume_yes) {
|
|
||||||
/* ask for permission */
|
|
||||||
g_print ("\n%s [y|N]: ",
|
|
||||||
/* TRANSLATORS: should the branch be changed */
|
|
||||||
_("Do you understand the consequences of changing the firmware branch?"));
|
|
||||||
if (!fu_util_prompt_for_boolean (FALSE)) {
|
|
||||||
g_set_error_literal (error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_NOTHING_TO_DO,
|
|
||||||
"Declined branch switch");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_util_switch_branch (FuUtilPrivate *priv, gchar **values, GError **error)
|
fu_util_switch_branch (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||||
{
|
{
|
||||||
@ -2049,7 +1996,7 @@ fu_util_switch_branch (FuUtilPrivate *priv, gchar **values, GError **error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* we're switching branch */
|
/* we're switching branch */
|
||||||
if (!fu_util_switch_branch_warning (priv, dev, rel, error))
|
if (!fu_util_switch_branch_warning (dev, rel, priv->assume_yes, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* update the console if composite devices are also updated */
|
/* update the console if composite devices are also updated */
|
||||||
|
Loading…
Reference in New Issue
Block a user