diff options
author | Sebastian Heinlein <devel@glatzor.de> | 2011-12-09 09:20:32 +0100 |
---|---|---|
committer | Sebastian Heinlein <devel@glatzor.de> | 2011-12-09 11:14:53 +0100 |
commit | af5596aec207414915f3780ba535f5c7f8e2c827 (patch) | |
tree | beecf77fab86164c542f71b9c373c24af0e3ccfd | |
parent | d157648c084dbc7883411b63ad915b03ef025619 (diff) |
Add new roles SimulateRepairSystem and RepairSystem
This allows to recover from a broken package management system,
e.g. if a package with unsatisfied dependencies has been forced to
install using a low level tool like rpm or dpkg or if the system
was shut down during an installation.
-rw-r--r-- | backends/box/pk-backend-box.c | 2 | ||||
-rw-r--r-- | backends/opkg/pk-backend-opkg.c | 2 | ||||
-rw-r--r-- | backends/pisi/pk-backend-pisi.c | 2 | ||||
-rw-r--r-- | client/pk-console.c | 7 | ||||
-rwxr-xr-x | contrib/pk-completion.bash | 1 | ||||
-rw-r--r-- | lib/packagekit-glib2/pk-client-sync.c | 113 | ||||
-rw-r--r-- | lib/packagekit-glib2/pk-client-sync.h | 13 | ||||
-rw-r--r-- | lib/packagekit-glib2/pk-client.c | 143 | ||||
-rw-r--r-- | lib/packagekit-glib2/pk-client.h | 16 | ||||
-rw-r--r-- | lib/packagekit-glib2/pk-enum.c | 2 | ||||
-rw-r--r-- | lib/packagekit-glib2/pk-enum.h | 2 | ||||
-rw-r--r-- | lib/packagekit-glib2/pk-self-test.c | 3 | ||||
-rw-r--r-- | lib/packagekit-glib2/pk-task-sync.c | 49 | ||||
-rw-r--r-- | lib/packagekit-glib2/pk-task-sync.h | 6 | ||||
-rw-r--r-- | lib/packagekit-glib2/pk-task.c | 62 | ||||
-rw-r--r-- | lib/packagekit-glib2/pk-task.h | 6 | ||||
-rw-r--r-- | lib/python/packagekit/backend.py | 22 | ||||
-rw-r--r-- | src/org.freedesktop.PackageKit.Transaction.xml | 58 | ||||
-rw-r--r-- | src/pk-backend.c | 34 | ||||
-rw-r--r-- | src/pk-backend.h | 8 | ||||
-rw-r--r-- | src/pk-transaction.c | 102 |
21 files changed, 649 insertions, 4 deletions
diff --git a/backends/box/pk-backend-box.c b/backends/box/pk-backend-box.c index a6f930af..59eba276 100644 --- a/backends/box/pk-backend-box.c +++ b/backends/box/pk-backend-box.c @@ -736,6 +736,8 @@ PK_BACKEND_OPTIONS ( NULL, /* simulate_remove_packages */ NULL, /* simulate_update_packages */ NULL, /* upgrade_system */ + NULL, /* repair_system */ + NULL, /* simulate_repair_system */ NULL, /* transaction_start */ NULL /* transaction_stop */ ); diff --git a/backends/opkg/pk-backend-opkg.c b/backends/opkg/pk-backend-opkg.c index e0b77d9e..27ab92ce 100644 --- a/backends/opkg/pk-backend-opkg.c +++ b/backends/opkg/pk-backend-opkg.c @@ -752,6 +752,8 @@ PK_BACKEND_OPTIONS ( NULL, /* simulate_remove_packages */ NULL, /* simulate_update_packages */ NULL, /* upgrade_system */ + NULL, /* repair_system */ + NULL, /* simulate_repair_system */ NULL, /* transaction_start */ NULL /* transaction_stop */ ); diff --git a/backends/pisi/pk-backend-pisi.c b/backends/pisi/pk-backend-pisi.c index 9635708d..9392658a 100644 --- a/backends/pisi/pk-backend-pisi.c +++ b/backends/pisi/pk-backend-pisi.c @@ -400,6 +400,8 @@ PK_BACKEND_OPTIONS ( NULL, /* simulate_remove_packages */ NULL, /* simulate_update_packages */ NULL, /* upgrade_system */ + NULL, /* repair_system */ + NULL, /* simulate_repair_system */ NULL, /* transaction_start */ NULL /* transaction_stop */ ); diff --git a/client/pk-console.c b/client/pk-console.c index 9ea7eef1..2636bdc2 100644 --- a/client/pk-console.c +++ b/client/pk-console.c @@ -1220,6 +1220,8 @@ pk_console_get_summary (void) g_string_append_printf (string, " %s\n", "accept-eula [eula-id]"); if (pk_bitfield_contain (roles, PK_ROLE_ENUM_GET_CATEGORIES)) g_string_append_printf (string, " %s\n", "get-categories"); + if (pk_bitfield_contain (roles, PK_ROLE_ENUM_REPAIR_SYSTEM)) + g_string_append_printf (string, " %s\n", "repair"); return g_string_free (string, FALSE); } @@ -1785,6 +1787,11 @@ main (int argc, char *argv[]) (PkProgressCallback) pk_console_progress_cb, NULL, (GAsyncReadyCallback) pk_console_finished_cb, NULL); + } else if (strcmp (mode, "repair") == 0) { + pk_task_repair_system_async (PK_TASK(task), cancellable, + (PkProgressCallback) pk_console_progress_cb, NULL, + (GAsyncReadyCallback) pk_console_finished_cb, NULL); + } else { /* TRANSLATORS: The user tried to use an unsupported option on the command line */ error = g_error_new (1, 0, _("Option '%s' is not supported"), mode); diff --git a/contrib/pk-completion.bash b/contrib/pk-completion.bash index bae7db7e..6decb411 100755 --- a/contrib/pk-completion.bash +++ b/contrib/pk-completion.bash @@ -46,6 +46,7 @@ __pkcon_commandlist=" search update upgrade-system + repair " __pkconcomp () diff --git a/lib/packagekit-glib2/pk-client-sync.c b/lib/packagekit-glib2/pk-client-sync.c index 654de096..0b666a24 100644 --- a/lib/packagekit-glib2/pk-client-sync.c +++ b/lib/packagekit-glib2/pk-client-sync.c @@ -1680,7 +1680,6 @@ pk_client_simulate_update_packages (PkClient *client, gchar **package_ids, GCanc return results; } - /** * pk_client_upgrade_system: * @distro_id: a distro ID such as "fedora-14" @@ -1736,6 +1735,118 @@ pk_client_upgrade_system (PkClient *client, const gchar *distro_id, PkUpgradeKin } /** + * pk_client_repair_system: + * @only_trusted: if only trusted packages should be installed + * @cancellable: a #GCancellable or %NULL + * @progress_callback: (scope call): the function to run when the progress changes + * @progress_user_data: data to pass to @progress_callback + * @error: the #GError to store any failure, or %NULL + * + * This transaction will try to recover from a broken package management system: + * e.g. the installation of a package with unsatisfied dependencies has + * been forced by using a low level tool (rpm or dpkg) or the + * system was shutdown during processing an installation. + * + * The backend will decide what is best to do. + * + * Warning: this function is synchronous, and may block. Do not use it in GUI + * applications. + * + * Return value: (transfer full): a %PkResults object, or NULL for error + * + * Since: 0.7.2 + **/ +PkResults * +pk_client_repair_system (PkClient *client, + gboolean only_trusted, + GCancellable *cancellable, + PkProgressCallback progress_callback, + gpointer progress_user_data, GError **error) +{ + PkClientHelper *helper; + PkResults *results; + + g_return_val_if_fail (PK_IS_CLIENT (client), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + /* create temp object */ + helper = g_new0 (PkClientHelper, 1); + helper->loop = g_main_loop_new (NULL, FALSE); + helper->error = error; + + /* run async method */ + pk_client_repair_system_async (client, only_trusted, + cancellable, progress_callback, progress_user_data, + (GAsyncReadyCallback) pk_client_generic_finish_sync, + helper); + + g_main_loop_run (helper->loop); + + results = helper->results; + + /* free temp object */ + g_main_loop_unref (helper->loop); + g_free (helper); + + return results; +} + +/** + * pk_client_simulate_repair_system: + * @cancellable: a #GCancellable or %NULL + * @progress_callback: (scope call): the function to run when the progress changes + * @progress_user_data: data to pass to @progress_callback + * @error: the #GError to store any failure, or %NULL + * + * This transaction simultes the recovery from a broken package management system: + * e.g. the installation of a package with unsatisfied dependencies has + * been forced by using a low level tool (rpm or dpkg) or the + * system was shutdown during processing an installation. + * + * The backend will decide what is best to do. + * + * Warning: this function is synchronous, and may block. Do not use it in GUI + * applications. + * + * Return value: (transfer full): a %PkResults object, or NULL for error + * + * Since: 0.7.2 + **/ +PkResults * +pk_client_simulate_repair_system (PkClient *client, + GCancellable *cancellable, + PkProgressCallback progress_callback, + gpointer progress_user_data, GError **error) +{ + PkClientHelper *helper; + PkResults *results; + + g_return_val_if_fail (PK_IS_CLIENT (client), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + /* create temp object */ + helper = g_new0 (PkClientHelper, 1); + helper->loop = g_main_loop_new (NULL, FALSE); + helper->error = error; + + /* run async method */ + pk_client_simulate_repair_system_async (client, + cancellable, progress_callback, progress_user_data, + (GAsyncReadyCallback) pk_client_generic_finish_sync, + helper); + + g_main_loop_run (helper->loop); + + results = helper->results; + + /* free temp object */ + g_main_loop_unref (helper->loop); + g_free (helper); + + return results; +} + +/** * pk_client_adopt: * @client: a valid #PkClient instance * @transaction_id: a transaction ID such as "/21_ebcbdaae_data" diff --git a/lib/packagekit-glib2/pk-client-sync.h b/lib/packagekit-glib2/pk-client-sync.h index e162c3e1..d5140792 100644 --- a/lib/packagekit-glib2/pk-client-sync.h +++ b/lib/packagekit-glib2/pk-client-sync.h @@ -289,6 +289,19 @@ PkResults *pk_client_upgrade_system (PkClient *client, gpointer progress_user_data, GError **error); +PkResults *pk_client_repair_system (PkClient *client, + gboolean only_trusted, + GCancellable *cancellable, + PkProgressCallback progress_callback, + gpointer progress_user_data, + GError **error); + +PkResults *pk_client_simulate_repair_system (PkClient *client, + GCancellable *cancellable, + PkProgressCallback progress_callback, + gpointer progress_user_data, + GError **error); + PkResults *pk_client_adopt (PkClient *client, const gchar *transaction_id, GCancellable *cancellable, diff --git a/lib/packagekit-glib2/pk-client.c b/lib/packagekit-glib2/pk-client.c index 0bf22471..c7443d29 100644 --- a/lib/packagekit-glib2/pk-client.c +++ b/lib/packagekit-glib2/pk-client.c @@ -1803,6 +1803,15 @@ pk_client_set_hints_cb (DBusGProxy *proxy, DBusGProxyCall *call, PkClientState * G_TYPE_STRING, state->distro_id, G_TYPE_STRING, pk_upgrade_kind_enum_to_string (state->upgrade_kind), G_TYPE_INVALID); + } else if (state->role == PK_ROLE_ENUM_REPAIR_SYSTEM) { + state->call = dbus_g_proxy_begin_call (state->proxy, "RepairSystem", + (DBusGProxyCallNotify) pk_client_method_cb, state, NULL, + G_TYPE_BOOLEAN, state->only_trusted, + G_TYPE_INVALID); + } else if (state->role == PK_ROLE_ENUM_SIMULATE_REPAIR_SYSTEM) { + state->call = dbus_g_proxy_begin_call (state->proxy, "SimulateRepairSystem", + (DBusGProxyCallNotify) pk_client_method_cb, state, NULL, + G_TYPE_INVALID); } else { g_assert_not_reached (); } @@ -4238,7 +4247,6 @@ out: g_object_unref (res); } - /** * pk_client_upgrade_system_async: * @client: a valid #PkClient instance @@ -4305,6 +4313,139 @@ out: g_object_unref (res); } +/** + * pk_client_repair_system_async: + * @client: a valid #PkClient instance + * @only_trusted: only trusted packages should be installed + * @cancellable: a #GCancellable or %NULL + * @progress_callback: (scope call): the function to run when the progress changes + * @progress_user_data: data to pass to @progress_callback + * @callback_ready: the function to run on completion + * @user_data: the data to pass to @callback_ready + * + * This transaction will try to recover from a broken package management system: + * e.g. the installation of a package with unsatisfied dependencies has + * been forced by the user using a low level tool (rpm or dpkg) or the + * system was shutdown during processing an installation. + * + * The backend will decide what is best to do. + * + * Since: 0.7.2 + **/ +void +pk_client_repair_system_async (PkClient *client, + gboolean only_trusted, + GCancellable *cancellable, + PkProgressCallback progress_callback, + gpointer progress_user_data, + GAsyncReadyCallback callback_ready, gpointer user_data) +{ + GSimpleAsyncResult *res; + PkClientState *state; + GError *error = NULL; + + g_return_if_fail (PK_IS_CLIENT (client)); + g_return_if_fail (callback_ready != NULL); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + + res = g_simple_async_result_new (G_OBJECT (client), callback_ready, user_data, pk_client_repair_system_async); + + /* save state */ + state = g_slice_new0 (PkClientState); + state->role = PK_ROLE_ENUM_REPAIR_SYSTEM; + state->res = g_object_ref (res); + state->client = g_object_ref (client); + if (cancellable != NULL) { + state->cancellable = g_object_ref (cancellable); + state->cancellable_id = g_cancellable_connect (cancellable, G_CALLBACK (pk_client_cancellable_cancel_cb), state, NULL); + } + state->only_trusted = only_trusted; + state->progress_callback = progress_callback; + state->progress_user_data = progress_user_data; + state->progress = pk_progress_new (); + + /* check not already cancelled */ + if (cancellable != NULL && g_cancellable_set_error_if_cancelled (cancellable, &error)) { + pk_client_state_finish (state, error); + g_error_free (error); + goto out; + } + + /* identify */ + pk_client_set_role (state, state->role); + + /* get tid */ + pk_control_get_tid_async (client->priv->control, cancellable, (GAsyncReadyCallback) pk_client_get_tid_cb, state); +out: + g_object_unref (res); +} + +/** + * pk_client_simulate_repair_system_async: + * @client: a valid #PkClient instance + * @only_trusted: only trusted packages should be installed + * @cancellable: a #GCancellable or %NULL + * @progress_callback: (scope call): the function to run when the progress changes + * @progress_user_data: data to pass to @progress_callback + * @callback_ready: the function to run on completion + * @user_data: the data to pass to @callback_ready + * + * This transaction simulates a recovery from a broken package management system: + * e.g. the installation of a package with unsatisfied dependencies has + * been forced by the user using a low level tool (rpm or dpkg) or the + * system was shutdown during processing an installation. + * + * The backend will decide what is best to do. + * + * Since: 0.7.2 + **/ +void +pk_client_simulate_repair_system_async (PkClient *client, + GCancellable *cancellable, + PkProgressCallback progress_callback, + gpointer progress_user_data, + GAsyncReadyCallback callback_ready, + gpointer user_data) +{ + GSimpleAsyncResult *res; + PkClientState *state; + GError *error = NULL; + + g_return_if_fail (PK_IS_CLIENT (client)); + g_return_if_fail (callback_ready != NULL); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + + res = g_simple_async_result_new (G_OBJECT (client), callback_ready, user_data, pk_client_repair_system_async); + + /* save state */ + state = g_slice_new0 (PkClientState); + state->role = PK_ROLE_ENUM_SIMULATE_REPAIR_SYSTEM; + state->res = g_object_ref (res); + state->client = g_object_ref (client); + if (cancellable != NULL) { + state->cancellable = g_object_ref (cancellable); + state->cancellable_id = g_cancellable_connect (cancellable, G_CALLBACK (pk_client_cancellable_cancel_cb), state, NULL); + } + state->progress_callback = progress_callback; + state->progress_user_data = progress_user_data; + state->progress = pk_progress_new (); + + /* check not already cancelled */ + if (cancellable != NULL && g_cancellable_set_error_if_cancelled (cancellable, &error)) { + pk_client_state_finish (state, error); + g_error_free (error); + goto out; + } + + /* identify */ + pk_client_set_role (state, state->role); + + /* get tid */ + pk_control_get_tid_async (client->priv->control, cancellable, (GAsyncReadyCallback) pk_client_get_tid_cb, state); +out: + g_object_unref (res); +} + /***************************************************************************************************/ /** diff --git a/lib/packagekit-glib2/pk-client.h b/lib/packagekit-glib2/pk-client.h index 11c2badc..a4d24541 100644 --- a/lib/packagekit-glib2/pk-client.h +++ b/lib/packagekit-glib2/pk-client.h @@ -402,6 +402,22 @@ void pk_client_upgrade_system_async (PkClient *client, GAsyncReadyCallback callback_ready, gpointer user_data); +void pk_client_repair_system_async (PkClient *client, + gboolean only_trusted, + GCancellable *cancellable, + PkProgressCallback progress_callback, + gpointer progress_user_data, + GAsyncReadyCallback callback_ready, + gpointer user_data); + + +void pk_client_simulate_repair_system_async (PkClient *client, + GCancellable *cancellable, + PkProgressCallback progress_callback, + gpointer progress_user_data, + GAsyncReadyCallback callback_ready, + gpointer user_data); + void pk_client_adopt_async (PkClient *client, const gchar *transaction_id, GCancellable *cancellable, diff --git a/lib/packagekit-glib2/pk-enum.c b/lib/packagekit-glib2/pk-enum.c index 918c5322..cfad3f52 100644 --- a/lib/packagekit-glib2/pk-enum.c +++ b/lib/packagekit-glib2/pk-enum.c @@ -127,6 +127,8 @@ static const PkEnumMatch enum_role[] = { {PK_ROLE_ENUM_SIMULATE_REMOVE_PACKAGES, "simulate-remove-packages"}, {PK_ROLE_ENUM_SIMULATE_UPDATE_PACKAGES, "simulate-update-packages"}, {PK_ROLE_ENUM_UPGRADE_SYSTEM, "upgrade-system"}, + {PK_ROLE_ENUM_REPAIR_SYSTEM, "repair-system"}, + {PK_ROLE_ENUM_SIMULATE_REPAIR_SYSTEM, "simulate-repair-system"}, {0, NULL} }; diff --git a/lib/packagekit-glib2/pk-enum.h b/lib/packagekit-glib2/pk-enum.h index bb217561..bae65b23 100644 --- a/lib/packagekit-glib2/pk-enum.h +++ b/lib/packagekit-glib2/pk-enum.h @@ -85,6 +85,8 @@ typedef enum { PK_ROLE_ENUM_SIMULATE_REMOVE_PACKAGES, PK_ROLE_ENUM_SIMULATE_UPDATE_PACKAGES, PK_ROLE_ENUM_UPGRADE_SYSTEM, /* Since: 0.6.11 */ + PK_ROLE_ENUM_REPAIR_SYSTEM, /* Since: 0.7.2 */ + PK_ROLE_ENUM_SIMULATE_REPAIR_SYSTEM, /* Since: 0.7.2 */ PK_ROLE_ENUM_LAST } PkRoleEnum; diff --git a/lib/packagekit-glib2/pk-self-test.c b/lib/packagekit-glib2/pk-self-test.c index f35b6e2e..ea2beafc 100644 --- a/lib/packagekit-glib2/pk-self-test.c +++ b/lib/packagekit-glib2/pk-self-test.c @@ -956,7 +956,8 @@ pk_test_control_get_properties_cb (GObject *object, GAsyncResult *res, gpointer "refresh-cache;remove-packages;repo-enable;repo-set-data;resolve;rollback;" "search-details;search-file;search-group;search-name;update-packages;update-system;" "what-provides;download-packages;get-distro-upgrades;simulate-install-packages;" - "simulate-remove-packages;simulate-update-packages;upgrade-system"); + "simulate-remove-packages;simulate-update-packages;upgrade-system;" + "repair-system;simulate-repair-system"); g_free (text); /* check filters */ diff --git a/lib/packagekit-glib2/pk-task-sync.c b/lib/packagekit-glib2/pk-task-sync.c index ff04ac90..4d8b226b 100644 --- a/lib/packagekit-glib2/pk-task-sync.c +++ b/lib/packagekit-glib2/pk-task-sync.c @@ -1150,3 +1150,52 @@ pk_task_repo_enable_sync (PkTask *task, const gchar *repo_id, gboolean enabled, return results; } +/** + * pk_task_repair_system_sync: + * @task: a valid #PkTask instance + * @cancellable: a #GCancellable or %NULL + * @progress_callback: the function to run when the progress changes + * @progress_user_data: data to pass to @progress_callback + * @error: the #GError to store any failure, or %NULL + * + * Recover from broken dependencies of installed packages or incomplete + * installations. + * + * Warning: this function is synchronous, and may block. Do not use it in GUI + * applications. + * + * Return value: a %PkResults object, or NULL for error + * + * Since: 0.7.2 + **/ +PkResults * +pk_task_repair_system_sync (PkTask *task, GCancellable *cancellable, + PkProgressCallback progress_callback, gpointer progress_user_data, + GError **error) +{ + PkTaskHelper *helper; + PkResults *results; + + g_return_val_if_fail (PK_IS_TASK (task), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + /* create temp object */ + helper = g_new0 (PkTaskHelper, 1); + helper->loop = g_main_loop_new (NULL, FALSE); + helper->error = error; + + /* run async method */ + pk_task_repair_system_async (task, cancellable, progress_callback, progress_user_data, + (GAsyncReadyCallback) pk_task_generic_finish_sync, + helper); + + g_main_loop_run (helper->loop); + + results = helper->results; + + /* free temp object */ + g_main_loop_unref (helper->loop); + g_free (helper); + + return results; +} diff --git a/lib/packagekit-glib2/pk-task-sync.h b/lib/packagekit-glib2/pk-task-sync.h index fb9fc355..492a4dea 100644 --- a/lib/packagekit-glib2/pk-task-sync.h +++ b/lib/packagekit-glib2/pk-task-sync.h @@ -210,6 +210,12 @@ PkResults *pk_task_repo_enable_sync (PkTask *task, gpointer progress_user_data, GError **error); +PkResults *pk_task_repair_system_sync (PkTask *task, + GCancellable *cancellable, + PkProgressCallback progress_callback, + gpointer progress_user_data, + GError **error); + G_END_DECLS #endif /* __PK_TASK_SYNC_H */ diff --git a/lib/packagekit-glib2/pk-task.c b/lib/packagekit-glib2/pk-task.c index 6bddfc83..b8d40c1e 100644 --- a/lib/packagekit-glib2/pk-task.c +++ b/lib/packagekit-glib2/pk-task.c @@ -272,6 +272,10 @@ pk_task_do_async_action (PkTaskState *state) pk_client_repo_enable_async (PK_CLIENT(state->task), state->repo_id, state->enabled, state->cancellable, state->progress_callback, state->progress_user_data, (GAsyncReadyCallback) pk_task_ready_cb, state); + } else if (state->role == PK_ROLE_ENUM_REPAIR_SYSTEM) { + pk_client_repair_system_async (PK_CLIENT(state->task), state->only_trusted, + state->cancellable, state->progress_callback, state->progress_user_data, + (GAsyncReadyCallback) pk_task_ready_cb, state); } else { g_assert_not_reached (); } @@ -430,6 +434,12 @@ pk_task_do_async_simulate_action (PkTaskState *state) pk_client_simulate_install_files_async (PK_CLIENT(state->task), state->files, state->cancellable, state->progress_callback, state->progress_user_data, (GAsyncReadyCallback) pk_task_simulate_ready_cb, state); + } else if (state->role == PK_ROLE_ENUM_REPAIR_SYSTEM) { + /* simulate repair system async */ + g_debug ("doing repair system"); + pk_client_simulate_repair_system_async (PK_CLIENT(state->task), + state->cancellable, state->progress_callback, state->progress_user_data, + (GAsyncReadyCallback) pk_task_simulate_ready_cb, state); } else { g_assert_not_reached (); } @@ -2141,6 +2151,58 @@ pk_task_repo_enable_async (PkTask *task, const gchar *repo_id, gboolean enabled, } /** + * pk_task_repair_system_async: + * @task: a valid #PkTask instance + * @cancellable: a #GCancellable or %NULL + * @progress_callback: (scope call): the function to run when the progress changes + * @progress_user_data: data to pass to @progress_callback + * @callback_ready: the function to run on completion + * @user_data: the data to pass to @callback_ready + * + * Recover the system from broken dependencies and aborted installations. + * + * Since: 0.7.2 + **/ +void +pk_task_repair_system_async (PkTask *task, GCancellable *cancellable, + PkProgressCallback progress_callback, gpointer progress_user_data, + GAsyncReadyCallback callback_ready, gpointer user_data) +{ + GSimpleAsyncResult *res; + PkTaskState *state; + PkTaskClass *klass = PK_TASK_GET_CLASS (task); + + g_return_if_fail (PK_IS_CLIENT (task)); + g_return_if_fail (callback_ready != NULL); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + + res = g_simple_async_result_new (G_OBJECT (task), callback_ready, user_data, pk_task_repair_system_async); + + /* save state */ + state = g_slice_new0 (PkTaskState); + state->role = PK_ROLE_ENUM_REPAIR_SYSTEM; + state->res = g_object_ref (res); + state->task = g_object_ref (task); + if (cancellable != NULL) + state->cancellable = g_object_ref (cancellable); + state->only_trusted = TRUE; + state->progress_callback = progress_callback; + state->progress_user_data = progress_user_data; + state->request = pk_task_generate_request_id (); + + g_debug ("adding state %p", state); + g_ptr_array_add (task->priv->array, state); + + /* start trusted repair system async */ + if (task->priv->simulate && klass->simulate_question != NULL) + pk_task_do_async_simulate_action (state); + else + pk_task_do_async_action (state); + + g_object_unref (res); +} + +/** * pk_task_generic_finish: * @task: a valid #PkTask instance * @res: the #GAsyncResult diff --git a/lib/packagekit-glib2/pk-task.h b/lib/packagekit-glib2/pk-task.h index de40af61..93a1f4c1 100644 --- a/lib/packagekit-glib2/pk-task.h +++ b/lib/packagekit-glib2/pk-task.h @@ -268,6 +268,12 @@ void pk_task_repo_enable_async (PkTask *task, gpointer progress_user_data, GAsyncReadyCallback callback_ready, gpointer user_data); +void pk_task_repair_system_async (PkTask *task, + GCancellable *cancellable, + PkProgressCallback progress_callback, + gpointer progress_user_data, + GAsyncReadyCallback callback_ready, + gpointer user_data); gboolean pk_task_user_accepted (PkTask *task, guint request); diff --git a/lib/python/packagekit/backend.py b/lib/python/packagekit/backend.py index 47714699..0fff1bbe 100644 --- a/lib/python/packagekit/backend.py +++ b/lib/python/packagekit/backend.py @@ -621,6 +621,22 @@ class PackageKitBaseBackend: ''' self.error(ERROR_NOT_SUPPORTED, "This function is not implemented in this backend", exit=False) + def repair_system(self, only_trusted): + ''' + Implement the {backend}-repair-system functionality + Needed to be implemented in a sub class + ''' + self.error(ERROR_NOT_SUPPORTED, "This function is not implemented in this backend", + exit=False) + + def simulate_repair_system(self): + ''' + Implement the {backend}-simulate-repair-system functionality + Needed to be implemented in a sub class + ''' + self.error(ERROR_NOT_SUPPORTED, "This function is not implemented in this backend", + exit=False) + def customTracebackHandler(self, tb): ''' Custom Traceback Handler @@ -793,6 +809,12 @@ class PackageKitBaseBackend: elif cmd == 'upgrade-system': self.upgrade_system(args[0]) self.finished() + elif cmd == 'repair-system': + self.repair_system(args[0]) + self.finished() + elif cmd == 'simulate-repair-system': + self.simulate_repair_system() + self.finished() else: errmsg = "command '%s' is not known" % cmd self.error(ERROR_INTERNAL_ERROR, errmsg, exit=False) diff --git a/src/org.freedesktop.PackageKit.Transaction.xml b/src/org.freedesktop.PackageKit.Transaction.xml index debeb572..8a9972c1 100644 --- a/src/org.freedesktop.PackageKit.Transaction.xml +++ b/src/org.freedesktop.PackageKit.Transaction.xml @@ -1640,6 +1640,64 @@ </method> <!--*****************************************************************************************--> + <method name="SimulateRepairSystem"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <doc:doc> + <doc:description> + <doc:para> + This method simulates recovering the package management system from e.g. + unsatisfied dependencies of installed packages emitting packages required to be + installed, removed, updated, reinstalled, downgraded, obsoleted or untrusted. + The latter is used to present the user untrusted packages that are about to be installed. + </doc:para> + <doc:para> + This method typically emits + <doc:tt>Progress</doc:tt>, + <doc:tt>Status</doc:tt> and + <doc:tt>Error</doc:tt> and + <doc:tt>Package</doc:tt>. + </doc:para> + </doc:description> + </doc:doc> + </method> + + <!--*****************************************************************************************--> + <method name="RepairSystem"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <doc:doc> + <doc:description> + <doc:para> + This method recovers the package management system from e.g. + unsatisfied dependencies of installed packages. + </doc:para> + <doc:para> + This method typically emits + <doc:tt>Progress</doc:tt>, + <doc:tt>Status</doc:tt> and + <doc:tt>Error</doc:tt> and + <doc:tt>Package</doc:tt>. + </doc:para> + </doc:description> + </doc:doc> + <arg type="b" name="only_trusted" direction="in"> + <doc:doc> + <doc:summary> + <doc:para> + If the transaction is only allowed to install trusted packages. + Unsigned packages should not be installed if this parameter is <doc:tt>TRUE</doc:tt>. + </doc:para> + <doc:para> + If this method is can only install trusted packages, and the packages are unsigned, then + the backend will send a <doc:tt>ErrorCode(missing-gpg-signature)</doc:tt>. + On recieving this error, the client may choose to retry with only_trusted <doc:tt>FALSE</doc:tt> + after gaining further authentication. + </doc:para> + </doc:summary> + </doc:doc> + </arg> + </method> + + <!--*****************************************************************************************--> <signal name="Category"> <doc:doc> <doc:description> diff --git a/src/pk-backend.c b/src/pk-backend.c index 2ed71e11..e3c36559 100644 --- a/src/pk-backend.c +++ b/src/pk-backend.c @@ -328,6 +328,10 @@ pk_backend_get_roles (PkBackend *backend) pk_bitfield_add (roles, PK_ROLE_ENUM_SIMULATE_UPDATE_PACKAGES); if (desc->upgrade_system != NULL) pk_bitfield_add (roles, PK_ROLE_ENUM_UPGRADE_SYSTEM); + if (desc->repair_system != NULL) + pk_bitfield_add (roles, PK_ROLE_ENUM_REPAIR_SYSTEM); + if (desc->simulate_repair_system != NULL) + pk_bitfield_add (roles, PK_ROLE_ENUM_SIMULATE_REPAIR_SYSTEM); backend->priv->roles = roles; out: return backend->priv->roles; @@ -672,6 +676,8 @@ pk_backend_set_name (PkBackend *backend, const gchar *backend_name, GError **err g_module_symbol (handle, "pk_backend_update_system", (gpointer *)&desc->update_system); g_module_symbol (handle, "pk_backend_what_provides", (gpointer *)&desc->what_provides); g_module_symbol (handle, "pk_backend_upgrade_system", (gpointer *)&desc->upgrade_system); + g_module_symbol (handle, "pk_backend_repair_system", (gpointer *)&desc->repair_system); + g_module_symbol (handle, "pk_backend_simulate_repair_system", (gpointer *)&desc->simulate_repair_system); /* get old static string data */ ret = g_module_symbol (handle, "pk_backend_get_author", (gpointer *)&backend_vfunc); @@ -3797,6 +3803,34 @@ pk_backend_upgrade_system (PkBackend *backend, const gchar *distro_id, PkUpgrade } /** + * pk_backend_repair_system: + */ +void +pk_backend_repair_system (PkBackend *backend, gboolean only_trusted) +{ + g_return_if_fail (PK_IS_BACKEND (backend)); + g_return_if_fail (backend->priv->desc->repair_system != NULL); + pk_backend_set_role_internal (backend, PK_ROLE_ENUM_REPAIR_SYSTEM); + pk_store_set_bool (backend->priv->store, "only_trusted", only_trusted); + pk_backend_transaction_reset (backend); + backend->priv->desc->repair_system (backend, only_trusted); +} + +/** + * pk_backend_simulate_repair_system: + */ +void +pk_backend_simulate_repair_system (PkBackend *backend) +{ + g_return_if_fail (PK_IS_BACKEND (backend)); + g_return_if_fail (backend->priv->desc->repair_system != NULL); + pk_backend_set_role_internal (backend, PK_ROLE_ENUM_SIMULATE_REPAIR_SYSTEM); + pk_backend_set_bool (backend, "hint:simulate", TRUE); + pk_backend_transaction_reset (backend); + backend->priv->desc->simulate_repair_system (backend); +} + +/** * pk_backend_init: **/ static void diff --git a/src/pk-backend.h b/src/pk-backend.h index 86ee2304..a3ed2646 100644 --- a/src/pk-backend.h +++ b/src/pk-backend.h @@ -204,6 +204,9 @@ void pk_backend_simulate_update_packages (PkBackend *backend, void pk_backend_upgrade_system (PkBackend *backend, const gchar *distro_id, PkUpgradeKindEnum upgrade_kind); +void pk_backend_repair_system (PkBackend *backend, + gboolean only_trusted); +void pk_backend_simulate_repair_system (PkBackend *backend); /* set the state */ gboolean pk_backend_accept_eula (PkBackend *backend, @@ -483,7 +486,10 @@ typedef struct { const gchar *distro_id, PkUpgradeKindEnum upgrade_kind); void (*transaction_reset) (PkBackend *backend); - gpointer padding[6]; + void (*repair_system) (PkBackend *backend, + gboolean only_trusted); + void (*simulate_repair_system) (PkBackend *backend); + gpointer padding[4]; } PkBackendDesc; G_END_DECLS diff --git a/src/pk-transaction.c b/src/pk-transaction.c index 11028b8d..449b7608 100644 --- a/src/pk-transaction.c +++ b/src/pk-transaction.c @@ -2155,6 +2155,10 @@ pk_transaction_run (PkTransaction *transaction) pk_backend_simulate_update_packages (priv->backend, priv->cached_package_ids); } else if (priv->role == PK_ROLE_ENUM_UPGRADE_SYSTEM) { pk_backend_upgrade_system (priv->backend, priv->cached_value, priv->cached_provides); + } else if (priv->role == PK_ROLE_ENUM_REPAIR_SYSTEM) { + pk_backend_repair_system (priv->backend, priv->cached_only_trusted); + } else if (priv->role == PK_ROLE_ENUM_SIMULATE_REPAIR_SYSTEM) { + pk_backend_simulate_repair_system (priv->backend); } else { g_error ("failed to run as role not assigned"); ret = FALSE; @@ -2591,6 +2595,9 @@ pk_transaction_role_to_action_only_trusted (PkRoleEnum role) case PK_ROLE_ENUM_UPGRADE_SYSTEM: policy = "org.freedesktop.packagekit.upgrade-system"; break; + case PK_ROLE_ENUM_REPAIR_SYSTEM: + policy = "org.freedesktop.packagekit.package-install"; + break; default: break; } @@ -5475,6 +5482,91 @@ out: } /** + * pk_transaction_simulate_repair_system: + **/ +static void +pk_transaction_simulate_repair_system (PkTransaction *transaction, + GVariant *params, + GDBusMethodInvocation *context) +{ + gboolean ret; + GError *error = NULL; + + g_return_if_fail (PK_IS_TRANSACTION (transaction)); + g_return_if_fail (transaction->priv->tid != NULL); + + g_debug ("SimulateRepairSystem method called"); + + /* not implemented yet */ + if (!pk_backend_is_implemented (transaction->priv->backend, + PK_ROLE_ENUM_SIMULATE_REPAIR_SYSTEM)) { + error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_NOT_SUPPORTED, + "SimulateRepairSystem not supported by backend"); + pk_transaction_release_tid (transaction); + goto out; + } + + /* save so we can run later */ + pk_transaction_set_role (transaction, PK_ROLE_ENUM_SIMULATE_REPAIR_SYSTEM); + + /* try to commit this */ + ret = pk_transaction_commit (transaction); + if (!ret) { + error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_COMMIT_FAILED, + "Could not commit to a transaction object"); + pk_transaction_release_tid (transaction); + goto out; + } +out: + pk_transaction_dbus_return (context, error); +} + + +/** + * pk_transaction_repair_system: + **/ +static void +pk_transaction_repair_system (PkTransaction *transaction, + GVariant *params, + GDBusMethodInvocation *context) +{ + gboolean ret; + GError *error = NULL; + gboolean only_trusted; + + g_return_if_fail (PK_IS_TRANSACTION (transaction)); + g_return_if_fail (transaction->priv->tid != NULL); + + g_variant_get (params, "(b)", &only_trusted); + + g_debug ("RepairSystem method called (only trusted %i)", only_trusted); + + /* not implemented yet */ + if (!pk_backend_is_implemented (transaction->priv->backend, + PK_ROLE_ENUM_REPAIR_SYSTEM)) { + error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_NOT_SUPPORTED, + "RepairSystem not supported by backend"); + pk_transaction_release_tid (transaction); + goto out; + } + + /* save so we can run later */ + transaction->priv->cached_only_trusted = only_trusted; + pk_transaction_set_role (transaction, PK_ROLE_ENUM_REPAIR_SYSTEM); + + /* try to get authorization */ + ret = pk_transaction_obtain_authorization (transaction, + only_trusted, + PK_ROLE_ENUM_REPAIR_SYSTEM, &error); + if (!ret) { + pk_transaction_release_tid (transaction); + goto out; + } +out: + pk_transaction_dbus_return (context, error); +} + +/** * _g_variant_new_maybe_string: **/ static GVariant * @@ -5751,6 +5843,16 @@ pk_transaction_method_call (GDBusConnection *connection_, const gchar *sender, pk_transaction_upgrade_system (transaction, parameters, invocation); goto out; } + + if (g_strcmp0 (method_name, "RepairSystem") == 0) { + pk_transaction_repair_system (transaction, parameters, invocation); + goto out; + } + + if (g_strcmp0 (method_name, "SimulateRepairSystem") == 0) { + pk_transaction_simulate_repair_system (transaction, parameters, invocation); + goto out; + } out: return; } |