diff --git a/client/pk-console.c b/client/pk-console.c index fef0a1731..8346b4b6c 100644 --- a/client/pk-console.c +++ b/client/pk-console.c @@ -1703,6 +1703,8 @@ pk_console_get_summary (void) g_string_append_printf (string, " %s\n", "get-update-detail [package]"); if (pk_bitfield_contain (roles, PK_ROLE_ENUM_GET_PACKAGES)) g_string_append_printf (string, " %s\n", "get-packages"); + if (pk_bitfield_contain (roles, PK_ROLE_ENUM_ROLLBACK)) + g_string_append_printf (string, " %s\n", "rollback"); if (pk_bitfield_contain (roles, PK_ROLE_ENUM_GET_REPO_LIST)) g_string_append_printf (string, " %s\n", "repo-list"); if (pk_bitfield_contain (roles, PK_ROLE_ENUM_REPO_ENABLE)) @@ -1972,6 +1974,14 @@ main (int argc, char *argv[]) ret = pk_client_accept_eula (client_async, value, &error); maybe_sync = FALSE; + } else if (strcmp (mode, "rollback") == 0) { + if (value == NULL) { + /* TRANSLATORS: geeky error, 99.9999% of users won't see this */ + error = g_error_new (1, 0, "%s", _("A transaction identifier (tid) is required")); + goto out; + } + ret = pk_client_rollback (client_async, value, &error); + } else if (strcmp (mode, "update") == 0) { if (value == NULL) { /* do the system update */ diff --git a/lib/packagekit-glib/pk-client.c b/lib/packagekit-glib/pk-client.c index 7e2ab784b..68debd3f8 100644 --- a/lib/packagekit-glib/pk-client.c +++ b/lib/packagekit-glib/pk-client.c @@ -2264,6 +2264,29 @@ pk_client_get_update_detail (PkClient *client, gchar **package_ids, GError **err return ret; } +/** + * pk_client_rollback_action: + **/ +static gboolean +pk_client_rollback_action (PkClient *client, const gchar *transaction_id, GError **error) +{ + gboolean ret; + + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (PK_IS_CLIENT (client), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* check to see if we have a valid proxy */ + if (client->priv->proxy == NULL) { + *error = g_error_new (PK_CLIENT_ERROR, PK_CLIENT_ERROR_NO_TID, "No proxy for transaction"); + return FALSE; + } + ret = dbus_g_proxy_call (client->priv->proxy, "Rollback", error, + G_TYPE_STRING, transaction_id, + G_TYPE_INVALID, G_TYPE_INVALID); + return ret; +} + /** * pk_client_rollback: * @client: a valid #PkClient instance @@ -2279,6 +2302,7 @@ gboolean pk_client_rollback (PkClient *client, const gchar *transaction_id, GError **error) { gboolean ret; + GError *error_local = NULL; g_return_val_if_fail (PK_IS_CLIENT (client), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); @@ -2299,15 +2323,33 @@ pk_client_rollback (PkClient *client, const gchar *transaction_id, GError **erro client->priv->role = PK_ROLE_ENUM_ROLLBACK; client->priv->cached_transaction_id = g_strdup (transaction_id); - /* check to see if we have a valid proxy */ - if (client->priv->proxy == NULL) { - if (error != NULL) - *error = g_error_new (PK_CLIENT_ERROR, PK_CLIENT_ERROR_NO_TID, "No proxy for transaction"); - return FALSE; + /* hopefully do the operation first time */ + ret = pk_client_rollback_action (client, transaction_id, &error_local); + + /* we were refused by policy */ + if (!ret && pk_client_error_refused_by_policy (error_local)) { + /* try to get auth */ + if (pk_client_error_auth_obtain (error_local)) { + /* clear old error */ + g_clear_error (&error_local); + + /* get a new tid */ + ret = pk_client_allocate_transaction_id (client, &error_local); + if (!ret) + goto out; + + /* retry the action now we have got auth */ + ret = pk_client_rollback_action (client, transaction_id, &error_local); + } } - ret = dbus_g_proxy_call (client->priv->proxy, "Rollback", error, - G_TYPE_STRING, transaction_id, - G_TYPE_INVALID, G_TYPE_INVALID); + +out: + /* we failed one of these, return the error to the user */ + if (!ret) { + pk_client_error_fixup (&error_local); + g_propagate_error (error, error_local); + } + if (ret && !client->priv->is_finished) { /* allow clients to respond in the status changed callback */ pk_client_change_status (client, PK_STATUS_ENUM_WAIT); @@ -2316,7 +2358,7 @@ pk_client_rollback (PkClient *client, const gchar *transaction_id, GError **erro if (client->priv->synchronous) g_main_loop_run (client->priv->loop); } - pk_client_error_fixup (error); + return ret; }