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 /lib | |
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.
Diffstat (limited to 'lib')
-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 |
12 files changed, 434 insertions, 3 deletions
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) |