From 50a2f21a743d4f9b412cab4215702bc5105642f5 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Fri, 15 Nov 2024 10:47:32 +0000 Subject: [PATCH] ctl: Don't call Fetch() if Poll() found no update Calling Poll() causes a state change first to Polling, and then to one of the following: - Error - UpdateAvailable - Ready, which indicates that the poll was successful but no update is available. Previously, in that last case, `eos-updater-ctl update` would go ahead and try to call `Fetch()` anyway, leading to a scary Python backtrace: Traceback (most recent call last): File "/usr/bin/eos-updater-ctl", line 427, in main() File "/usr/bin/eos-updater-ctl", line 423, in main sys.exit(args.function(**args_dict)) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/bin/eos-updater-ctl", line 226, in command_update fetch_result = command_fetch(block=True, quiet=quiet, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/bin/eos-updater-ctl", line 209, in command_fetch return command_dbus('fetch', block, quiet, parameters) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/bin/eos-updater-ctl", line 177, in command_dbus proxy.call_sync(qualified_method_name, parameters, 0, -1, None) gi.repository.GLib.GError: g-io-error-quark: GDBus.Error:com.endlessm.Updater.Error.WrongState: Can't call Fetch() while in state Ready (36) Handle this case more gracefully by printing an explanatory message then exiting cleanly. https://phabricator.endlessm.com/T26906 --- eos-updater-ctl/eos-updater-ctl | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/eos-updater-ctl/eos-updater-ctl b/eos-updater-ctl/eos-updater-ctl index 49be8069..bc75e01d 100755 --- a/eos-updater-ctl/eos-updater-ctl +++ b/eos-updater-ctl/eos-updater-ctl @@ -234,16 +234,39 @@ def command_cancel(block, quiet=False): def command_update(quiet=False, force=False, timeout=0): """Run the entire update process.""" - poll_result = command_poll(block=True, quiet=quiet) + bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None) + proxy = Gio.DBusProxy.new_sync(bus, 0, None, + BUS_NAME, + OBJECT_PATH, + INTERFACE, + None) + + state = proxy.get_cached_property("State").get_uint32() + if UPDATER_STATES[state] == "UpdateApplied": + if not quiet: + dump_daemon_properties(proxy) + return 0 + + poll_result = command_with_proxy(proxy, 'poll', block=True, quiet=quiet) if poll_result != 0: return poll_result - fetch_result = command_fetch(block=True, quiet=quiet, - force=force, timeout=timeout) + state = proxy.get_cached_property("State").get_uint32() + if UPDATER_STATES[state] == "Ready": + print("No update available") + return 0 + + fetch_parameters = GLib.Variant('(a{sv})', ({ + 'force': GLib.Variant('b', force), + 'scheduling-timeout-seconds': GLib.Variant('u', timeout), + },)) + fetch_result = command_with_proxy( + proxy, 'fetch', block=True, quiet=quiet, parameters=fetch_parameters, + ) if fetch_result != 0: return fetch_result - apply_result = command_apply(block=True, quiet=quiet) + apply_result = command_with_proxy(proxy, 'apply', block=True, quiet=quiet) if apply_result != 0: return apply_result