summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Heinlein <devel@glatzor.de>2011-12-09 09:20:32 +0100
committerSebastian Heinlein <devel@glatzor.de>2011-12-09 11:14:53 +0100
commitaf5596aec207414915f3780ba535f5c7f8e2c827 (patch)
treebeecf77fab86164c542f71b9c373c24af0e3ccfd
parentd157648c084dbc7883411b63ad915b03ef025619 (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.c2
-rw-r--r--backends/opkg/pk-backend-opkg.c2
-rw-r--r--backends/pisi/pk-backend-pisi.c2
-rw-r--r--client/pk-console.c7
-rwxr-xr-xcontrib/pk-completion.bash1
-rw-r--r--lib/packagekit-glib2/pk-client-sync.c113
-rw-r--r--lib/packagekit-glib2/pk-client-sync.h13
-rw-r--r--lib/packagekit-glib2/pk-client.c143
-rw-r--r--lib/packagekit-glib2/pk-client.h16
-rw-r--r--lib/packagekit-glib2/pk-enum.c2
-rw-r--r--lib/packagekit-glib2/pk-enum.h2
-rw-r--r--lib/packagekit-glib2/pk-self-test.c3
-rw-r--r--lib/packagekit-glib2/pk-task-sync.c49
-rw-r--r--lib/packagekit-glib2/pk-task-sync.h6
-rw-r--r--lib/packagekit-glib2/pk-task.c62
-rw-r--r--lib/packagekit-glib2/pk-task.h6
-rw-r--r--lib/python/packagekit/backend.py22
-rw-r--r--src/org.freedesktop.PackageKit.Transaction.xml58
-rw-r--r--src/pk-backend.c34
-rw-r--r--src/pk-backend.h8
-rw-r--r--src/pk-transaction.c102
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;
}