Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Lachu:SystemServices
Lachu-PackageKit
0001-Added-initial-integration-with-bonsole-and...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0001-Added-initial-integration-with-bonsole-and-servicesU.patch of Package Lachu-PackageKit
From e2e49bc0947450329215d39ebb913bac6654c290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C5=82awomir=20Lach?= <slawek@lach.art.pl> Date: Mon, 17 Aug 2020 16:25:02 +0200 Subject: [PATCH 01/46] - Added initial integration with bonsole and servicesUI --- backends/zypp/meson.build | 2 + backends/zypp/pk-backend-zypp.cpp | 409 +++++++++++++++++++++++++++++- src/pk-backend.h | 3 +- src/pk-scheduler.c | 3 + src/pk-transaction.c | 9 + src/pk-transaction.h | 2 + 6 files changed, 413 insertions(+), 15 deletions(-) diff --git a/backends/zypp/meson.build b/backends/zypp/meson.build index a773ca1d0..248e82342 100644 --- a/backends/zypp/meson.build +++ b/backends/zypp/meson.build @@ -16,6 +16,8 @@ shared_module( packagekit_glib2_dep, zypp_dep, gmodule_dep, + dependency('libbonsole'), + dependency('dbus-1'), ], cpp_args: [ '-DPK_COMPILATION=1', diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp index 2c1250331..87a042c27 100644 --- a/backends/zypp/pk-backend-zypp.cpp +++ b/backends/zypp/pk-backend-zypp.cpp @@ -24,6 +24,9 @@ #include "config.h" +#include <bonsole_client.h> +#include <dbus/dbus.h> + #include <iterator> #include <list> #include <map> @@ -281,7 +284,8 @@ struct InstallResolvableReportReceiver : public zypp::callback::ReceiveReport<zy virtual Action problem (zypp::Resolvable::constPtr resolvable, Error error, const std::string &description, RpmLevel level) { pk_backend_job_error_code (_job, PK_ERROR_ENUM_PACKAGE_FAILED_TO_INSTALL, "%s", description.c_str ()); - return ABORT; + + return ABORT; } virtual void finish (zypp::Resolvable::constPtr resolvable, Error error, const std::string &reason, RpmLevel level) { @@ -551,6 +555,7 @@ class PkBackendZYppPrivate { std::vector<std::string> signatures; EventDirector eventDirector; PkBackendJob *currentJob; + bool isBonsoleInit; pthread_mutex_t zypp_mutex; }; @@ -1434,6 +1439,269 @@ zypp_backend_pool_item_notify (PkBackendJob *job, /** * simulate, or perform changes in pool to the system */ +/* LIBXML/LIBXSLT includes - remove unnecessary in future */ +#include <libxml/xmlmemory.h> +#include <libxml/debugXML.h> +#include <libxml/HTMLtree.h> +#include <libxml/xmlIO.h> +#include <libxml/DOCBparser.h> +#include <libxml/xinclude.h> +#include <libxml/catalog.h> +#include <libxslt/xslt.h> +#include <libxslt/xsltInternals.h> +#include <libxslt/transform.h> +#include <libxslt/xsltutils.h> + +struct msg_proc_helper { + + ResolverProblemList::iterator it; + ResolverProblemList problems; + Resolver_Ptr resolver; +}; + +static void show_solutions(const char *msg_, intptr_t usr_p) +{ + char *buffer, *prev, *curr, *prev2; + int length, length2; + int problem, solution; + xmlNodePtr root, text, anchor, message, form, checkbox; + struct msg_proc_helper *helper = (struct msg_proc_helper *) usr_p; + + ResolverProblemList::iterator it; + ProblemSolutionList::const_iterator sol_it; + + + xmlDocPtr a = bonsole_window(nullptr); + root = xmlDocGetRootElement(a); + + form = xmlNewNode(NULL, BAD_CAST "form"); + xmlSetProp(form, BAD_CAST "action",BAD_CAST "app:update"); + xmlAddChild(root, form); + + problem = 0; + solution = 0; + for (it = helper->problems.begin(); it != helper->problems.end(); ++it) { + + text = xmlNewText(BAD_CAST (*it)->description ().c_str ()); + xmlAddChild(form, text); + for (sol_it = (**it).solutions().begin(); sol_it != (**it).solutions().end(); ++sol_it) { + + checkbox = xmlNewNode(NULL, BAD_CAST "checkbox"); + text = xmlNewText(BAD_CAST (*sol_it)->description ().c_str ()); + xmlAddChild(checkbox, text); + + xmlAddChild(form, checkbox); + //text = xmlNewCDataBlock(a, BAD_CAST (*sol_it)->details ().c_str (), strlen((*sol_it)->details ().c_str ())); + char *string= strdup((*sol_it)->details ().c_str ()); + + char *prev = string; + char *curr = string; + + while ('\0' != *curr) { + + if ('\n' == *curr) { + + *curr = '\0'; + text = xmlNewText(BAD_CAST prev); + xmlAddChild(form, text); + text = xmlNewNode(NULL, BAD_CAST "br"); + xmlAddChild(form, text); + prev = curr + 1; + } + + ++curr; + } + + text = xmlNewText(BAD_CAST prev); + xmlAddChild(checkbox, text); + free(string); + + + length = snprintf(NULL, 0, "%d_%d", problem, solution) + 1; + buffer = (char*) malloc(length); + snprintf(buffer, length, "%d_%d", problem, solution); + + xmlSetProp(checkbox, BAD_CAST "name", BAD_CAST buffer); + + + free(buffer); + + ++solution; + } + ++problem; + } + +bonsole_window_release(nullptr); +bonsole_flush_changes(nullptr); +} + +static void message_proc(const char *msg__, intptr_t usr_p) +{ + ProblemSolutionList *solution_list; + char *buffer, *prev, *curr, *prev2; + int length, length2; + int problem, solution; + xmlNodePtr root, text, anchor, message, form, checkbox; + struct msg_proc_helper *helper = (struct msg_proc_helper *) usr_p; + + char *msg_ = strdup(msg__); + + if (0 == strncmp("update?", msg_, sizeof("update?") - 1)) { + + solution_list = new ProblemSolutionList(); + bonsole_reset_document(nullptr); + xmlDocPtr a = bonsole_window(nullptr); + root = xmlDocGetRootElement(a); + buffer = msg_; + length = 0; + while ('\0' != *buffer) { + + if ('&' == *buffer) { + + ++length; + *buffer = '\0'; + } + ++buffer; + } + ++length; + buffer = &msg_[sizeof("update?") - 1]; + + while (0 < length) { + + prev = buffer; + do { + + ++buffer; + } while ('_' != *buffer); + + *buffer = '\0'; + ++buffer; + do { + ++buffer; + } while ('=' != *buffer); + + + ++buffer; + if ('\0' != buffer[0] && 0 != strcmp(buffer, "1")) { + + --length; + do { + ++buffer; + } while ('\0' != *buffer); + + continue; + } + + while ('\0' != *buffer) { + ++buffer; + } + + ++buffer; + curr = prev; + prev = buffer; + + length2 = length - 1; + while (0 < length2) { + prev2 = buffer; + + + + do { + + ++buffer; + } while ('_' != *buffer); + + *buffer = '\0'; + ++buffer; + + + if (0 != strcmp(curr, prev2)) { + + --length2; + do { + ++buffer; + } while ('\0' != *buffer); + + continue; + } + + do { + ++buffer; + } while ('=' != *buffer); + + + ++buffer; + if ('\0' != buffer[0] && 0 != strcmp(buffer, "1")) { + + --length2; + do { + ++buffer; + } while ('\0' != *buffer); + + ++buffer; + if ('\0' != *buffer) { + + ++buffer; + } + continue; + } + message = xmlNewNode(NULL, BAD_CAST "message"); + text = xmlNewText(BAD_CAST "You checked two different solutions for one problem"); + xmlAddChild(message, text); + xmlAddChild(root, message); + + bonsole_window_release(nullptr); + show_solutions(msg_, usr_p); + + return; + + do { + ++buffer; + } while ('\0' != *buffer); + + --length2; + } + + // Apply this solution + char *prev3; + int problem_number, solution_number; + + //curr = prev; + problem_number = atoi(curr); + while ('\0' != *curr) ++curr; + prev3 = ++curr; + while ('\0' != *curr && '=' != *curr) ++curr; + *curr = '\0'; + solution_number = atoi(prev3); + + ProblemSolutionList::const_iterator it2; + ResolverProblemList::iterator it = helper->problems.begin(); + std::advance( + it, + problem_number); + ResolverProblem problem = **it; + it2 = problem.solutions().begin(); + std::advance( + it2, + solution_number); + ProblemSolution solution = **it2; + //solution.apply(helper->resolver); + + solution_list->push_back(&solution); + --length; + } + + + helper->resolver->applySolutions(*solution_list); + bonsole_window_release(nullptr); + bonsole_flush_changes(nullptr); + + bonsole_quit_loop(nullptr); + } + + free(msg_); +} + static gboolean zypp_perform_execution (PkBackendJob *job, ZYpp::Ptr zypp, PerformType type, gboolean force, PkBitfield transaction_flags) { @@ -1451,36 +1719,148 @@ zypp_perform_execution (PkBackendJob *job, ZYpp::Ptr zypp, PerformType type, gbo pk_backend_job_set_percentage(job, 0); zypp->resolver ()->setIgnoreAlreadyRecommended (TRUE); pk_backend_job_set_percentage(job, 100); - if (!zypp->resolver ()->resolvePool ()) { + while (!zypp->resolver ()->resolvePool ()) { // Manual intervention required to resolve dependencies // TODO: Figure out what we need to do with PackageKit // to pull off interactive problem solving. ResolverProblemList problems = zypp->resolver ()->problems (); gchar * emsg = NULL, * tempmsg = NULL; + ResolverProblemList::iterator it = problems.begin (); - for (ResolverProblemList::iterator it = problems.begin (); it != problems.end (); ++it) { + + // TODO: Add support for passing request could be handled interactively + if (force) { + + for (ResolverProblemList::iterator it = problems.begin (); it != problems.end (); ++it) { if (emsg == NULL) { emsg = g_strdup ((*it)->description ().c_str ()); + } else { tempmsg = emsg; emsg = g_strconcat (emsg, "\n", (*it)->description ().c_str (), NULL); g_free (tempmsg); } - } + } - // reset the status of all touched PoolItems - ResPool pool = ResPool::instance (); - for (ResPool::const_iterator it = pool.begin (); it != pool.end (); ++it) { - if (it->status ().isToBeInstalled ()) + // reset the status of all touched PoolItems + ResPool pool = ResPool::instance (); + for (ResPool::const_iterator it = pool.begin (); it != pool.end (); ++it) { + if (it->status ().isToBeInstalled ()) it->statusReset (); - } - - pk_backend_job_error_code (job, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, "%s", emsg); - g_free (emsg); - - goto exit; + } + pk_backend_job_error_code (job, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, "%s", emsg); + + g_free (emsg); + + goto exit; + } + if (! priv->isBonsoleInit ) { + + DBusConnection *bus_connection; + DBusError error; + + dbus_error_init(&error); + bus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (bus_connection == NULL) { + if (dbus_error_is_set(&error)) { + printf("Error occurred, while trying to connect: %s\n", error.message); + } + else { + printf("Error occurred, while trying to connect\n"); + } + dbus_error_free(&error); + exit(1); + } + + + char *sender = backend->sender; + char *server, *cookie; + DBusPendingCall* pending; + DBusMessage* reply; + DBusMessageIter args; + + + DBusMessage* msg = dbus_message_new_method_call("pl.art.lach.slawek.apps.DaemonUI","/pl/art/lach/slawek/apps/DaemonUI", "pl.art.lach.slawek.apps.DaemonUI.client", "getListenerNameForClient"); + + if (msg == NULL) { + + goto exit; + } + + + dbus_message_iter_init_append(msg, &args); + + if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &sender)) { + + fprintf(stderr, "Out Of Memory!\n"); + exit(1); + } + + if (!dbus_connection_send_with_reply(bus_connection, msg, &pending, -1)) + { + dbus_message_unref(msg); + goto exit; + } + dbus_connection_flush(bus_connection); + dbus_message_unref(msg); + + dbus_pending_call_block(pending); + reply = dbus_pending_call_steal_reply(pending); + dbus_pending_call_unref(pending); + + if (NULL == reply) { + + puts("Error: No reply"); + goto exit; + } + + if(dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { + + puts("Error"); + char *emsg; + if (!dbus_message_get_args(reply, &error, DBUS_TYPE_STRING, &emsg, DBUS_TYPE_INVALID)) { + + puts("No error message provided"); + goto exit; + } + + puts(emsg); + goto exit; + } + + dbus_error_init(&error); + dbus_message_get_args(reply, &error, DBUS_TYPE_STRING, &server, DBUS_TYPE_STRING, &cookie, DBUS_TYPE_INVALID); + if (dbus_error_is_set(&error)) { + + puts(error.message); + goto exit; + } + + setenv("HOME", "/root", 0); + setenv("LANG", "EN_US", 0); + + setenv("BONSOLE_DBUS_SCOPE", "SYSTEM_BUS", 1); + setenv("BONSOLE_RUN_MODE", "ALWAYS_TRY_TO_LOGIN", 1); + setenv("BONSOLE_DBUS_NAME", server, 1); + setenv("BONSOLE_COOKIE", cookie, 1); + + int argc = 1; + char *argv[2] = {(char*)"packagekitd", (char*)NULL}; + + if (0 != bonsole_client_init(&argc, argv)) exit(1); + + priv->isBonsoleInit = true; + } + struct msg_proc_helper transaction_problems; + transaction_problems.problems = problems; + transaction_problems.it = problems.begin(); + transaction_problems.resolver = zypp->resolver (); + + bonsole_reset_document(nullptr); + show_solutions("", (intptr_t)(void*) &transaction_problems); + bonsole_main_loop(0, message_proc, (intptr_t)(void*)&transaction_problems); } switch (type) { @@ -1825,6 +2205,7 @@ pk_backend_initialize (GKeyFile *conf, PkBackend *backend) { /* create private area */ priv = new PkBackendZYppPrivate; + priv->isBonsoleInit = false; priv->currentJob = 0; priv->zypp_mutex = PTHREAD_MUTEX_INITIALIZER; zypp_logging (); diff --git a/src/pk-backend.h b/src/pk-backend.h index bd80f48fe..4ffc0ec21 100644 --- a/src/pk-backend.h +++ b/src/pk-backend.h @@ -34,7 +34,7 @@ #include <packagekit-glib2/pk-package-ids.h> #include <packagekit-glib2/pk-bitfield.h> -#include "pk-backend.h" + #include "pk-backend-job.h" G_BEGIN_DECLS @@ -52,6 +52,7 @@ typedef struct { GObject parent; PkBackendPrivate *priv; + char *sender; } PkBackend; typedef struct diff --git a/src/pk-scheduler.c b/src/pk-scheduler.c index 33395c539..9ada99831 100644 --- a/src/pk-scheduler.c +++ b/src/pk-scheduler.c @@ -684,6 +684,9 @@ pk_scheduler_create (PkScheduler *scheduler, pk_scheduler_item_free (item); return FALSE; } + + /* Set the sender id */ + pk_transaction_get_backend(item->transaction)->sender = strdup(sender); /* the client only has a finite amount of time to use the object, else it's destroyed */ item->commit_id = g_timeout_add_seconds (PK_SCHEDULER_CREATE_COMMIT_TIMEOUT, diff --git a/src/pk-transaction.c b/src/pk-transaction.c index 3ef5a12bf..ef1176b43 100644 --- a/src/pk-transaction.c +++ b/src/pk-transaction.c @@ -177,6 +177,13 @@ static guint signals[SIGNAL_LAST] = { 0 }; G_DEFINE_TYPE (PkTransaction, pk_transaction, G_TYPE_OBJECT) +PkBackend * +pk_transaction_get_backend(PkTransaction *transaction) +{ + g_return_val_if_fail (PK_IS_TRANSACTION (transaction), NULL); + return transaction->priv->backend; +} + GQuark pk_transaction_error_quark (void) { @@ -863,6 +870,8 @@ pk_transaction_get_backend_job (PkTransaction *transaction) return transaction->priv->job; } + + /** * pk_transaction_is_finished_with_lock_required: **/ diff --git a/src/pk-transaction.h b/src/pk-transaction.h index 8bb22dd8d..98171f268 100644 --- a/src/pk-transaction.h +++ b/src/pk-transaction.h @@ -90,6 +90,8 @@ void pk_transaction_reset_after_lock_error (PkTransaction *transaction); void pk_transaction_make_exclusive (PkTransaction *transaction); void pk_transaction_skip_auth_checks (PkTransaction *transaction, gboolean skip_checks); +PkBackend * +pk_transaction_get_backend(PkTransaction *transaction); G_END_DECLS -- 2.32.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor