File 0009-zypp-merge-all-backend-code-into-one-file-much-easie.patch of Package PackageKit.1418
From a8bd9cc44dab3dc53baa53e38709eac6674d0c06 Mon Sep 17 00:00:00 2001
From: Stephan Kulow <coolo@suse.de>
Date: Mon, 21 Jan 2013 16:05:57 +0100
Subject: [PATCH 1/2] zypp: merge all backend code into one file, much easier
to refactor
---
backends/zypp/Makefile.am | 4 +-
backends/zypp/pk-backend-zypp-private.h | 22 -
backends/zypp/pk-backend-zypp.cpp | 1762 +++++++++++++++++++++++++++++--
backends/zypp/zypp-events.h | 425 --------
backends/zypp/zypp-utils.cpp | 1222 ---------------------
backends/zypp/zypp-utils.h | 217 ----
6 files changed, 1704 insertions(+), 1948 deletions(-)
delete mode 100644 backends/zypp/pk-backend-zypp-private.h
delete mode 100644 backends/zypp/zypp-events.h
delete mode 100644 backends/zypp/zypp-utils.cpp
delete mode 100644 backends/zypp/zypp-utils.h
diff --git a/backends/zypp/Makefile.am b/backends/zypp/Makefile.am
index 92036df..253b593 100644
--- a/backends/zypp/Makefile.am
+++ b/backends/zypp/Makefile.am
@@ -4,9 +4,7 @@ AM_CPPFLAGS = \
#SUBDIRS = helpers
plugindir = $(PK_PLUGIN_DIR)
plugin_LTLIBRARIES = libpk_backend_zypp.la
-libpk_backend_zypp_la_SOURCES = \
- pk-backend-zypp.cpp \
- zypp-utils.cpp
+libpk_backend_zypp_la_SOURCES = pk-backend-zypp.cpp
libpk_backend_zypp_la_LIBADD = $(PK_PLUGIN_LIBS)
libpk_backend_zypp_la_LDFLAGS = -module -avoid-version $(ZYPP_LIBS)
libpk_backend_zypp_la_CFLAGS = $(PK_PLUGIN_CFLAGS) $(WARNINGFLAGS_CPP)
diff --git a/backends/zypp/pk-backend-zypp-private.h b/backends/zypp/pk-backend-zypp-private.h
deleted file mode 100644
index 5aa0d73..0000000
--- a/backends/zypp/pk-backend-zypp-private.h
+++ /dev/null
@@ -1,22 +0,0 @@
-
-#ifndef PK_BACKEND_ZYPP_PRIVATE_H
-#define PK_BACKEND_ZYPP_PRIVATE_H
-
-#include <map>
-#include <string>
-#include <vector>
-#include <pthread.h>
-
-#include "zypp-events.h"
-
-typedef struct {
-
- std::vector<std::string> signatures;
- EventDirector eventDirector;
- PkBackendJob *currentJob;
-
- pthread_mutex_t zypp_mutex;
-
-} PkBackendZYppPrivate;
-
-#endif
diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index bce60f2..c4f6e02 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -1,6 +1,9 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (c) 2007 Novell, Inc.
+ * Copyright (c) 2007 Boyd Timothy <btimothy@gmail.com>
+ * Copyright (c) 2007-2008 Stefan Haas <shaas@suse.de>
+ * Copyright (c) 2007-2008 Scott Reeves <sreeves@novell.com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -21,80 +24,1623 @@
#include "config.h"
-#include <gmodule.h>
+#include <iterator>
+#include <list>
+#include <map>
+#include <pthread.h>
+#include <set>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <sys/vfs.h>
+#include <unistd.h>
+#include <vector>
+
#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gmodule.h>
#include <pk-backend.h>
-#include <pk-backend-spawn.h>
#include <pk-shared.h>
-#include <unistd.h>
-#include <string>
-#include <set>
-#include <map>
-#include <list>
-#include <glib/gi18n.h>
-#include <sys/vfs.h>
+#define I_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE
+#include <packagekit-glib2/packagekit.h>
+#include <packagekit-glib2/pk-enum.h>
+#include <pk-backend-spawn.h>
+
+#include <zypp/Digest.h>
+#include <zypp/KeyRing.h>
+#include <zypp/Package.h>
+#include <zypp/Patch.h>
+#include <zypp/PathInfo.h>
+#include <zypp/Pathname.h>
+#include <zypp/Pattern.h>
+#include <zypp/PoolQuery.h>
+#include <zypp/Product.h>
+#include <zypp/RelCompare.h>
+#include <zypp/RepoInfo.h>
+#include <zypp/RepoInfo.h>
+#include <zypp/RepoManager.h>
+#include <zypp/Repository.h>
+#include <zypp/ResFilters.h>
+#include <zypp/ResObject.h>
+#include <zypp/ResPool.h>
+#include <zypp/ResPoolProxy.h>
+#include <zypp/Resolvable.h>
+#include <zypp/SrcPackage.h>
+#include <zypp/TmpPath.h>
+#include <zypp/ZYpp.h>
+#include <zypp/ZYppCallbacks.h>
+#include <zypp/ZYppFactory.h>
+#include <zypp/base/Algorithm.h>
+#include <zypp/base/Functional.h>
+#include <zypp/base/LogControl.h>
+#include <zypp/base/Logger.h>
+#include <zypp/base/String.h>
+#include <zypp/media/MediaManager.h>
+#include <zypp/parser/IniDict.h>
+#include <zypp/parser/ParseException.h>
+#include <zypp/parser/ProductFileReader.h>
+#include <zypp/repo/PackageProvider.h>
+#include <zypp/repo/RepoException.h>
+#include <zypp/repo/SrcPackageProvider.h>
+#include <zypp/sat/Pool.h>
+#include <zypp/sat/Solvable.h>
+#include <zypp/target/rpm/RpmDb.h>
+#include <zypp/target/rpm/RpmException.h>
+#include <zypp/target/rpm/RpmHeader.h>
+#include <zypp/target/rpm/librpmDb.h>
+#include <zypp/ui/Selectable.h>
+
+using namespace std;
+using namespace zypp;
+using zypp::filesystem::PathInfo;
+
+#undef ZYPP_BASE_LOGGER_LOGGROUP
+#define ZYPP_BASE_LOGGER_LOGGROUP "packagekit"
+
+typedef enum {
+ INSTALL,
+ REMOVE,
+ UPDATE
+} PerformType;
+
+
+class ZyppJob {
+ public:
+ ZyppJob(PkBackendJob *job);
+ ~ZyppJob();
+ zypp::ZYpp::Ptr get_zypp();
+};
+
+enum PkgSearchType {
+ SEARCH_TYPE_NAME = 0,
+ SEARCH_TYPE_DETAILS = 1,
+ SEARCH_TYPE_FILE = 2,
+ SEARCH_TYPE_RESOLVE = 3
+};
+
+// helper function to restore the pool status
+// after doing operations on it
+class PoolStatusSaver : private base::NonCopyable
+{
+public:
+ PoolStatusSaver() {
+ ResPool::instance().proxy().saveState();
+ }
+
+ ~PoolStatusSaver() {
+ ResPool::instance().proxy().restoreState();
+ }
+};
+
+/** A string to store the last refreshed repo
+ * this is needed for gpg-key handling stuff (UGLY HACK)
+ * FIXME
+ */
+gchar * _repoName;
+/** Used to show/install only an update to ourself. This way if we find a critical bug
+ * in the way we update packages we will install the fix before any other updates.
+ */
+gboolean _updating_self = FALSE;
+
+/**
+ * Build a package_id from the specified resolvable. The returned
+ * gchar * should be freed with g_free ().
+ */
+static gchar *
+zypp_build_package_id_from_resolvable (const sat::Solvable &resolvable)
+{
+ gchar *package_id;
+ const char *arch;
+
+ if (isKind<SrcPackage>(resolvable))
+ arch = "source";
+ else
+ arch = resolvable.arch ().asString ().c_str ();
+
+ string repo = resolvable.repository ().alias();
+ if (resolvable.isSystem())
+ repo = "installed";
+ package_id = pk_package_id_build (resolvable.name ().c_str (),
+ resolvable.edition ().asString ().c_str (),
+ arch, repo.c_str ());
+
+ return package_id;
+}
+
+namespace ZyppBackend
+{
+class PkBackendZYppPrivate;
+static PkBackendZYppPrivate *priv = 0;
+
+class ZyppBackendReceiver
+{
+public:
+ PkBackendJob *_job;
+ gchar *_package_id;
+ guint _sub_percentage;
+
+ ZyppBackendReceiver() {
+ _job = NULL;
+ _package_id = NULL;
+ _sub_percentage = 0;
+ }
+
+ virtual void clear_package_id () {
+ if (_package_id != NULL) {
+ g_free (_package_id);
+ _package_id = NULL;
+ }
+ }
+
+ bool zypp_signature_required (const PublicKey &key);
+ bool zypp_signature_required (const string &file);
+ bool zypp_signature_required (const string &file, const string &id);
+
+ void update_sub_percentage (guint percentage) {
+ // Only emit a percentage if it's different from the last
+ // percentage we emitted and it's divisible by ten. We
+ // don't want to overload dbus/GUI. Also account for the
+ // fact that libzypp may skip over a "divisible by ten"
+ // value (i.e., 28, 29, 31, 32).
+
+ MIL << percentage << " " << _sub_percentage << std::endl;
+ if (percentage <= _sub_percentage)
+ return;
+
+ if (!_package_id) {
+ MIL << "percentage without package" << std::endl;
+ return;
+ }
+
+ if (percentage > 100) {
+ MIL << "libzypp is silly" << std::endl;
+ return;
+ }
+
+ _sub_percentage = percentage;
+ pk_backend_job_set_item_progress(_job, _package_id, PK_STATUS_ENUM_UNKNOWN, _sub_percentage);
+ }
+
+ void reset_sub_percentage ()
+ {
+ _sub_percentage = 0;
+ //pk_backend_set_sub_percentage (_backend, _sub_percentage);
+ }
+
+protected:
+ ~ZyppBackendReceiver() {} // or a public virtual one
+};
+
+struct InstallResolvableReportReceiver : public zypp::callback::ReceiveReport<zypp::target::rpm::InstallResolvableReport>, ZyppBackendReceiver
+{
+ zypp::Resolvable::constPtr _resolvable;
+ bool preparing;
+ int last_value;
+
+ virtual void start (zypp::Resolvable::constPtr resolvable) {
+ clear_package_id ();
+ _package_id = zypp_build_package_id_from_resolvable (resolvable->satSolvable ());
+ MIL << resolvable << " " << _package_id << std::endl;
+ gchar* summary = g_strdup(zypp::asKind<zypp::ResObject>(resolvable)->summary().c_str ());
+ if (_package_id != NULL) {
+ pk_backend_job_set_status (_job, PK_STATUS_ENUM_INSTALL);
+ pk_backend_job_package (_job, PK_INFO_ENUM_INSTALLING, _package_id, summary);
+ reset_sub_percentage ();
+ }
+ // first we prepare then we install
+ preparing = true;
+ last_value = 0;
+ g_free (summary);
+ }
+
+ virtual bool progress (int value, zypp::Resolvable::constPtr resolvable) {
+ // we need to have extra logic here as progress is reported twice
+ // and PackageKit does not like percentages going back
+ if (preparing && value < last_value)
+ preparing = false;
+ last_value = value;
+ MIL << preparing << " " << value << " " << _package_id << std::endl;
+ int perc = 0;
+ if (preparing)
+ perc = value * 30 / 100;
+ else
+ perc = 30 + value * 70 / 100;
+ update_sub_percentage (perc);
+ return true;
+ }
+
+ virtual Action problem (zypp::Resolvable::constPtr resolvable, Error error, const std::string &description, RpmLevel level) {
+ //g_debug ("InstallResolvableReportReceiver::problem()");
+ return ABORT;
+ }
+
+ virtual void finish (zypp::Resolvable::constPtr resolvable, Error error, const std::string &reason, RpmLevel level) {
+ MIL << reason << " " << _package_id << " " << resolvable << std::endl;
+ if (_package_id != NULL) {
+ //pk_backend_job_package (_backend, PK_INFO_ENUM_INSTALLED, _package_id, "TODO: Put the package summary here if possible");
+ clear_package_id ();
+ }
+ }
+};
+
+struct RemoveResolvableReportReceiver : public zypp::callback::ReceiveReport<zypp::target::rpm::RemoveResolvableReport>, ZyppBackendReceiver
+{
+ zypp::Resolvable::constPtr _resolvable;
+
+ virtual void start (zypp::Resolvable::constPtr resolvable) {
+ clear_package_id ();
+ _package_id = zypp_build_package_id_from_resolvable (resolvable->satSolvable ());
+ if (_package_id != NULL) {
+ pk_backend_job_set_status (_job, PK_STATUS_ENUM_REMOVE);
+ pk_backend_job_package (_job, PK_INFO_ENUM_REMOVING, _package_id, "");
+ reset_sub_percentage ();
+ }
+ }
+
+ virtual bool progress (int value, zypp::Resolvable::constPtr resolvable) {
+ update_sub_percentage (value);
+ return true;
+ }
+
+ virtual Action problem (zypp::Resolvable::constPtr resolvable, Error error, const std::string &description) {
+ pk_backend_job_error_code (_job, PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE, description.c_str ());
+ return ABORT;
+ }
+
+ virtual void finish (zypp::Resolvable::constPtr resolvable, Error error, const std::string &reason) {
+ if (_package_id != NULL) {
+ pk_backend_job_package (_job, PK_INFO_ENUM_FINISHED, _package_id, "");
+ clear_package_id ();
+ }
+ }
+};
+
+struct RepoProgressReportReceiver : public zypp::callback::ReceiveReport<zypp::ProgressReport>, ZyppBackendReceiver
+{
+ virtual void start (const zypp::ProgressData &data)
+ {
+ g_debug ("_____________- RepoProgressReportReceiver::start()___________________");
+ reset_sub_percentage ();
+ }
+
+ virtual bool progress (const zypp::ProgressData &data)
+ {
+ //fprintf (stderr, "\n\n----> RepoProgressReportReceiver::progress(), %s:%d\n\n", data.name().c_str(), (int)data.val());
+ update_sub_percentage ((int)data.val ());
+ return true;
+ }
+
+ virtual void finish (const zypp::ProgressData &data)
+ {
+ //fprintf (stderr, "\n\n----> RepoProgressReportReceiver::finish()\n\n");
+ }
+};
+
+struct RepoReportReceiver : public zypp::callback::ReceiveReport<zypp::repo::RepoReport>, ZyppBackendReceiver
+{
+ virtual void start (const zypp::ProgressData &data, const zypp::RepoInfo)
+ {
+ g_debug ("______________________ RepoReportReceiver::start()________________________");
+ reset_sub_percentage ();
+ }
+
+ virtual bool progress (const zypp::ProgressData &data)
+ {
+ //fprintf (stderr, "\n\n----> RepoReportReceiver::progress(), %s:%d\n", data.name().c_str(), (int)data.val());
+ update_sub_percentage ((int)data.val ());
+ return true;
+ }
+
+ virtual void finish (zypp::Repository source, const std::string &task, zypp::repo::RepoReport::Error error, const std::string &reason)
+ {
+ //fprintf (stderr, "\n\n----> RepoReportReceiver::finish()\n");
+ }
+};
+
+struct DownloadProgressReportReceiver : public zypp::callback::ReceiveReport<zypp::repo::DownloadResolvableReport>, ZyppBackendReceiver
+{
+ virtual void start (zypp::Resolvable::constPtr resolvable, const zypp::Url &file)
+ {
+ MIL << resolvable << " " << file << std::endl;
+ clear_package_id ();
+ _package_id = zypp_build_package_id_from_resolvable (resolvable->satSolvable ());
+ gchar* summary = g_strdup(zypp::asKind<zypp::ResObject>(resolvable)->summary().c_str ());
+
+ fprintf (stderr, "DownloadProgressReportReceiver::start():%s --%s\n",
+ g_strdup (file.asString().c_str()), _package_id);
+ if (_package_id != NULL) {
+ pk_backend_job_set_status (_job, PK_STATUS_ENUM_DOWNLOAD);
+ pk_backend_job_package (_job, PK_INFO_ENUM_DOWNLOADING, _package_id, summary);
+ reset_sub_percentage ();
+ }
+ g_free(summary);
+ }
+
+ virtual bool progress (int value, zypp::Resolvable::constPtr resolvable)
+ {
+ MIL << resolvable << " " << value << " " << _package_id << std::endl;
+ update_sub_percentage (value);
+ //pk_backend_job_set_speed (_job, static_cast<guint>(dbps_current));
+ return true;
+ }
+
+ virtual void finish (zypp::Resolvable::constPtr resolvable, Error error, const std::string &konreason)
+ {
+ MIL << resolvable << " " << error << " " << _package_id << std::endl;
+ update_sub_percentage (100);
+ clear_package_id ();
+ }
+};
+
+struct MediaChangeReportReceiver : public zypp::callback::ReceiveReport<zypp::media::MediaChangeReport>, ZyppBackendReceiver
+{
+ virtual Action requestMedia (zypp::Url &url, unsigned mediaNr, const std::string &label, zypp::media::MediaChangeReport::Error error, const std::string &description, const std::vector<std::string> & devices, unsigned int &dev_current)
+ {
+ pk_backend_job_error_code (_job, PK_ERROR_ENUM_REPO_NOT_AVAILABLE, description.c_str ());
+ // We've to abort here, because there is currently no feasible way to inform the user to insert/change media
+ return ABORT;
+ }
+};
+
+struct ProgressReportReceiver : public zypp::callback::ReceiveReport<zypp::ProgressReport>, ZyppBackendReceiver
+{
+ virtual void start (const zypp::ProgressData &progress)
+ {
+ MIL << std::endl;
+ reset_sub_percentage ();
+ }
+
+ virtual bool progress (const zypp::ProgressData &progress)
+ {
+ MIL << progress.val() << std::endl;
+ update_sub_percentage ((int)progress.val ());
+ return true;
+ }
+
+ virtual void finish (const zypp::ProgressData &progress)
+ {
+ MIL << progress.val() << std::endl;
+ update_sub_percentage ((int)progress.val ());
+ }
+};
+
+// These last two are called -only- from zypp_refresh_meta_and_cache
+// *if this is not true* - we will get un-caught Abort exceptions.
+
+struct KeyRingReportReceiver : public zypp::callback::ReceiveReport<zypp::KeyRingReport>, ZyppBackendReceiver
+{
+ virtual zypp::KeyRingReport::KeyTrust askUserToAcceptKey (const zypp::PublicKey &key, const zypp::KeyContext &keycontext)
+ {
+ if (zypp_signature_required(key))
+ return KEY_TRUST_AND_IMPORT;
+ return KEY_DONT_TRUST;
+ }
+
+ virtual bool askUserToAcceptUnsignedFile (const std::string &file, const zypp::KeyContext &keycontext)
+ {
+ return zypp_signature_required (file);
+ }
+
+ virtual bool askUserToAcceptUnknownKey (const std::string &file, const std::string &id, const zypp::KeyContext &keycontext)
+ {
+ return zypp_signature_required(file, id);
+ }
+
+ virtual bool askUserToAcceptVerificationFailed (const std::string &file, const zypp::PublicKey &key, const zypp::KeyContext &keycontext)
+ {
+ return zypp_signature_required(key);
+ }
+
+};
+
+struct DigestReportReceiver : public zypp::callback::ReceiveReport<zypp::DigestReport>, ZyppBackendReceiver
+{
+ virtual bool askUserToAcceptNoDigest (const zypp::Pathname &file)
+ {
+ return zypp_signature_required(file.asString ());
+ }
+
+ virtual bool askUserToAcceptUnknownDigest (const zypp::Pathname &file, const std::string &name)
+ {
+ pk_backend_job_error_code(_job, PK_ERROR_ENUM_GPG_FAILURE, "Repo: %s Digest: %s", file.c_str (), name.c_str ());
+ return zypp_signature_required(file.asString ());
+ }
+
+ virtual bool askUserToAcceptWrongDigest (const zypp::Pathname &file, const std::string &requested, const std::string &found)
+ {
+ pk_backend_job_error_code(_job, PK_ERROR_ENUM_GPG_FAILURE, "For repo %s %s is requested but %s was found!",
+ file.c_str (), requested.c_str (), found.c_str ());
+ return zypp_signature_required(file.asString ());
+ }
+};
+
+class EventDirector
+{
+ private:
+ ZyppBackend::RepoReportReceiver _repoReport;
+ ZyppBackend::RepoProgressReportReceiver _repoProgressReport;
+ ZyppBackend::InstallResolvableReportReceiver _installResolvableReport;
+ ZyppBackend::RemoveResolvableReportReceiver _removeResolvableReport;
+ ZyppBackend::DownloadProgressReportReceiver _downloadProgressReport;
+ ZyppBackend::KeyRingReportReceiver _keyRingReport;
+ ZyppBackend::DigestReportReceiver _digestReport;
+ ZyppBackend::MediaChangeReportReceiver _mediaChangeReport;
+ ZyppBackend::ProgressReportReceiver _progressReport;
+
+ public:
+ EventDirector ()
+ {
+ _repoReport.connect ();
+ _repoProgressReport.connect ();
+ _installResolvableReport.connect ();
+ _removeResolvableReport.connect ();
+ _downloadProgressReport.connect ();
+ _keyRingReport.connect ();
+ _digestReport.connect ();
+ _mediaChangeReport.connect ();
+ _progressReport.connect ();
+ }
+
+ void setJob(PkBackendJob *job)
+ {
+ _repoReport._job = job;
+ _repoProgressReport._job = job;
+ _installResolvableReport._job = job;
+ _removeResolvableReport._job = job;
+ _downloadProgressReport._job = job;
+ _keyRingReport._job = job;
+ _digestReport._job = job;
+ _mediaChangeReport._job = job;
+ _progressReport._job = job;
+ }
+
+ ~EventDirector ()
+ {
+ _repoReport.disconnect ();
+ _repoProgressReport.disconnect ();
+ _installResolvableReport.disconnect ();
+ _removeResolvableReport.disconnect ();
+ _downloadProgressReport.disconnect ();
+ _keyRingReport.disconnect ();
+ _digestReport.disconnect ();
+ _mediaChangeReport.disconnect ();
+ _progressReport.disconnect ();
+ }
+};
+
+class PkBackendZYppPrivate {
+ public:
+ std::vector<std::string> signatures;
+ EventDirector eventDirector;
+ PkBackendJob *currentJob;
+
+ pthread_mutex_t zypp_mutex;
+};
+
+}; // namespace ZyppBackend
+
+using namespace ZyppBackend;
+
+ZyppJob::ZyppJob(PkBackendJob *job)
+{
+ MIL << "locking zypp" << std::endl;
+ pthread_mutex_lock(&priv->zypp_mutex);
+
+ if (priv->currentJob) {
+ MIL << "currentjob is already defined - highly impossible" << endl;
+ }
+
+ pk_backend_job_set_locked(job, true);
+ priv->currentJob = job;
+ priv->eventDirector.setJob(job);
+}
+
+ZyppJob::~ZyppJob()
+{
+ if (priv->currentJob)
+ pk_backend_job_set_locked(priv->currentJob, false);
+ priv->currentJob = 0;
+ priv->eventDirector.setJob(0);
+ MIL << "unlocking zypp" << std::endl;
+ pthread_mutex_unlock(&priv->zypp_mutex);
+}
+
+/**
+ * Initialize Zypp (Factory method)
+ */
+ZYpp::Ptr
+ZyppJob::get_zypp()
+{
+ static gboolean initialized = FALSE;
+ ZYpp::Ptr zypp = NULL;
+
+ try {
+ zypp = ZYppFactory::instance ().getZYpp ();
+
+ /* TODO: we need to lifecycle manage this, detect changes
+ in the requested 'root' etc. */
+ if (!initialized) {
+ filesystem::Pathname pathname("/");
+ zypp->initializeTarget (pathname);
+
+ initialized = TRUE;
+ }
+ } catch (const ZYppFactoryException &ex) {
+ pk_backend_job_error_code (priv->currentJob, PK_ERROR_ENUM_FAILED_INITIALIZATION, ex.asUserString().c_str() );
+ return NULL;
+ } catch (const Exception &ex) {
+ pk_backend_job_error_code (priv->currentJob, PK_ERROR_ENUM_INTERNAL_ERROR, ex.asUserString().c_str() );
+ return NULL;
+ }
+
+ return zypp;
+}
+
+
+
+
+/**
+ * Enable and rotate zypp logging
+ */
+gboolean
+zypp_logging ()
+{
+ gchar *file = g_strdup ("/var/log/pk_backend_zypp");
+ gchar *file_old = g_strdup ("/var/log/pk_backend_zypp-1");
+
+ if (g_file_test (file, G_FILE_TEST_EXISTS)) {
+ struct stat buffer;
+ g_stat (file, &buffer);
+ // if the file is bigger than 10 MB rotate
+ if ((guint)buffer.st_size > 10485760) {
+ if (g_file_test (file_old, G_FILE_TEST_EXISTS))
+ g_remove (file_old);
+ g_rename (file, file_old);
+ }
+ }
+
+ base::LogControl::instance ().logfile(file);
+
+ g_free (file);
+ g_free (file_old);
+
+ return TRUE;
+}
+
+gboolean
+zypp_is_changeable_media (const Url &url)
+{
+ gboolean is_cd = false;
+ try {
+ media::MediaManager mm;
+ media::MediaAccessId id = mm.open (url);
+ is_cd = mm.isChangeable (id);
+ mm.close (id);
+ } catch (const media::MediaException &e) {
+ // TODO: Do anything about this?
+ }
+
+ return is_cd;
+}
+
+namespace {
+ /// Helper finding pattern at end or embedded in name.
+ /// E.g '-debug' in 'repo-debug' or 'repo-debug-update'
+ inline bool
+ name_ends_or_contains( const std::string & name_r, const std::string & pattern_r, const char sepchar_r = '-' )
+ {
+ if ( ! pattern_r.empty() )
+ {
+ for ( std::string::size_type pos = name_r.find( pattern_r );
+ pos != std::string::npos;
+ pos = name_r.find( pattern_r, pos + pattern_r.size() ) )
+ {
+ if ( pos + pattern_r.size() == name_r.size() // at end
+ || name_r[pos + pattern_r.size()] == sepchar_r ) // embedded
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+gboolean
+zypp_is_development_repo (RepoInfo repo)
+{
+ return ( name_ends_or_contains( repo.alias(), "-debuginfo" )
+ || name_ends_or_contains( repo.alias(), "-debug" )
+ || name_ends_or_contains( repo.alias(), "-source" )
+ || name_ends_or_contains( repo.alias(), "-development" ) );
+}
+
+gboolean
+zypp_is_valid_repo (PkBackendJob *job, RepoInfo repo)
+{
+
+ if (repo.alias().empty()){
+ pk_backend_job_error_code (job, PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR, "Repository has no or invalid repo name defined.\n", repo.alias ().c_str ());
+ return FALSE;
+ }
+
+ if (!repo.url().isValid()){
+ pk_backend_job_error_code (job, PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR, "%s: Repository has no or invalid url defined.\n", repo.alias ().c_str ());
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * Build and return a ResPool that contains all local resolvables
+ * and ones found in the enabled repositories.
+ */
+ResPool
+zypp_build_pool (ZYpp::Ptr zypp, gboolean include_local)
+{
+ static gboolean repos_loaded = FALSE;
+
+ // the target is loaded or unloaded on request
+ if (include_local) {
+ // FIXME have to wait for fix in zypp (repeated loading of target)
+ if (sat::Pool::instance().reposFind( sat::Pool::systemRepoAlias() ).solvablesEmpty ())
+ {
+ // Add local resolvables
+ Target_Ptr target = zypp->target ();
+ target->load ();
+ }
+ } else {
+ if (!sat::Pool::instance().reposFind( sat::Pool::systemRepoAlias() ).solvablesEmpty ())
+ {
+ // Remove local resolvables
+ Repository repository = sat::Pool::instance ().reposFind (sat::Pool::systemRepoAlias());
+ repository.eraseFromPool ();
+ }
+ }
+
+ // we only load repositories once.
+ if (repos_loaded)
+ return zypp->pool();
+
+ // Add resolvables from enabled repos
+ RepoManager manager;
+ try {
+ for (RepoManager::RepoConstIterator it = manager.repoBegin(); it != manager.repoEnd(); ++it) {
+ RepoInfo repo (*it);
+
+ // skip disabled repos
+ if (repo.enabled () == false)
+ continue;
+ // skip not cached repos
+ if (manager.isCached (repo) == false) {
+ g_warning ("%s is not cached! Do a refresh", repo.alias ().c_str ());
+ continue;
+ }
+ //FIXME see above, skip already cached repos
+ if (sat::Pool::instance().reposFind( repo.alias ()) == Repository::noRepository)
+ manager.loadFromCache (repo);
+
+ }
+ repos_loaded = true;
+ } catch (const repo::RepoNoAliasException &ex) {
+ g_error ("Can't figure an alias to look in cache");
+ } catch (const repo::RepoNotCachedException &ex) {
+ g_error ("The repo has to be cached at first: %s", ex.asUserString ().c_str ());
+ } catch (const Exception &ex) {
+ g_error ("TODO: Handle exceptions: %s", ex.asUserString ().c_str ());
+ }
+
+ return zypp->pool ();
+}
+
+/**
+* check and warns the user that a repository may be outdated
+*/
+void
+warn_outdated_repos(PkBackendJob *job, const ResPool & pool)
+{
+ Repository repoobj;
+ ResPool::repository_iterator it;
+ for ( it = pool.knownRepositoriesBegin();
+ it != pool.knownRepositoriesEnd();
+ ++it )
+ {
+ Repository repo(*it);
+ if ( repo.maybeOutdated() )
+ {
+ // warn the user
+ pk_backend_job_message (job,
+ PK_MESSAGE_ENUM_BROKEN_MIRROR,
+ str::form("The repository %s seems to be outdated. You may want to try another mirror.",
+ repo.alias().c_str()).c_str() );
+ }
+ }
+}
+
+/**
+ * Return the rpmHeader of a package
+ */
+target::rpm::RpmHeader::constPtr
+zypp_get_rpmHeader (const string &name, Edition edition)
+{
+ target::rpm::librpmDb::db_const_iterator it;
+ target::rpm::RpmHeader::constPtr result = new target::rpm::RpmHeader ();
+
+ for (it.findPackage (name, edition); *it; ++it) {
+ result = *it;
+ }
+
+ return result;
+}
+
+/**
+ * Return the PkEnumGroup of the given PoolItem.
+ */
+PkGroupEnum
+get_enum_group (const string &group_)
+{
+ string group(str::toLower(group_));
+
+ if (group.find ("amusements") != string::npos) {
+ return PK_GROUP_ENUM_GAMES;
+ } else if (group.find ("development") != string::npos) {
+ return PK_GROUP_ENUM_PROGRAMMING;
+ } else if (group.find ("hardware") != string::npos) {
+ return PK_GROUP_ENUM_SYSTEM;
+ } else if (group.find ("archiving") != string::npos
+ || group.find("clustering") != string::npos
+ || group.find("system/monitoring") != string::npos
+ || group.find("databases") != string::npos
+ || group.find("system/management") != string::npos) {
+ return PK_GROUP_ENUM_ADMIN_TOOLS;
+ } else if (group.find ("graphics") != string::npos) {
+ return PK_GROUP_ENUM_GRAPHICS;
+ } else if (group.find ("multimedia") != string::npos) {
+ return PK_GROUP_ENUM_MULTIMEDIA;
+ } else if (group.find ("network") != string::npos) {
+ return PK_GROUP_ENUM_NETWORK;
+ } else if (group.find ("office") != string::npos
+ || group.find("text") != string::npos
+ || group.find("editors") != string::npos) {
+ return PK_GROUP_ENUM_OFFICE;
+ } else if (group.find ("publishing") != string::npos) {
+ return PK_GROUP_ENUM_PUBLISHING;
+ } else if (group.find ("security") != string::npos) {
+ return PK_GROUP_ENUM_SECURITY;
+ } else if (group.find ("telephony") != string::npos) {
+ return PK_GROUP_ENUM_COMMUNICATION;
+ } else if (group.find ("gnome") != string::npos) {
+ return PK_GROUP_ENUM_DESKTOP_GNOME;
+ } else if (group.find ("kde") != string::npos) {
+ return PK_GROUP_ENUM_DESKTOP_KDE;
+ } else if (group.find ("xfce") != string::npos) {
+ return PK_GROUP_ENUM_DESKTOP_XFCE;
+ } else if (group.find ("gui/other") != string::npos) {
+ return PK_GROUP_ENUM_DESKTOP_OTHER;
+ } else if (group.find ("localization") != string::npos) {
+ return PK_GROUP_ENUM_LOCALIZATION;
+ } else if (group.find ("system") != string::npos) {
+ return PK_GROUP_ENUM_SYSTEM;
+ } else if (group.find ("scientific") != string::npos) {
+ return PK_GROUP_ENUM_EDUCATION;
+ }
+
+ return PK_GROUP_ENUM_UNKNOWN;
+}
+
+/**
+ * Returns a list of packages that match the specified package_name.
+ */
+void
+zypp_get_packages_by_name (const gchar *package_name,
+ const ResKind kind,
+ vector<sat::Solvable> &result,
+ gboolean include_local = TRUE)
+{
+ ui::Selectable::Ptr sel( ui::Selectable::get( kind, package_name ) );
+ if ( sel ) {
+ if ( ! sel->installedEmpty() ) {
+ for_( it, sel->installedBegin(), sel->installedEnd() )
+ result.push_back( (*it).satSolvable() );
+ }
+ if ( ! sel->availableEmpty() ) {
+ for_( it, sel->availableBegin(), sel->availableEnd() )
+ result.push_back( (*it).satSolvable() );
+ }
+ }
+}
+
+/**
+ * Returns a list of packages that owns the specified file.
+ */
+void
+zypp_get_packages_by_file (ZYpp::Ptr zypp,
+ const gchar *search_file,
+ vector<sat::Solvable> &ret)
+{
+ ResPool pool = zypp_build_pool (zypp, TRUE);
+
+ string file (search_file);
+
+ target::rpm::librpmDb::db_const_iterator it;
+ target::rpm::RpmHeader::constPtr result = new target::rpm::RpmHeader ();
+
+ for (it.findByFile (search_file); *it; ++it) {
+ for (ResPool::byName_iterator it2 = pool.byNameBegin (it->tag_name ()); it2 != pool.byNameEnd (it->tag_name ()); it2++) {
+ if ((*it2)->isSystem ())
+ ret.push_back ((*it2)->satSolvable ());
+ }
+ }
+
+ if (ret.empty ()) {
+ Capability cap (search_file);
+ sat::WhatProvides prov (cap);
+
+ for(sat::WhatProvides::const_iterator it = prov.begin (); it != prov.end (); ++it) {
+ ret.push_back (*it);
+ }
+ }
+}
+
+/**
+ * Returns the Resolvable for the specified package_id.
+ * e.g. gnome-packagekit;3.6.1-132.1;x86_64;G:F
+*/
+sat::Solvable
+zypp_get_package_by_id (const gchar *package_id)
+{
+ MIL << package_id << endl;
+ if (!pk_package_id_check(package_id)) {
+ // TODO: Do we need to do something more for this error?
+ return sat::Solvable::noSolvable;
+ }
+
+ gchar **id_parts = pk_package_id_split(package_id);
+ const gchar *arch = id_parts[PK_PACKAGE_ID_ARCH];
+ if (!arch)
+ arch = "noarch";
+ bool want_source = !g_strcmp0 (arch, "source");
+
+ sat::Solvable package;
+
+ ResPool pool = ResPool::instance();
+
+ // Iterate over the resolvables and mark the one we want to check its dependencies
+ for (ResPool::byName_iterator it = pool.byNameBegin (id_parts[PK_PACKAGE_ID_NAME]);
+ it != pool.byNameEnd (id_parts[PK_PACKAGE_ID_NAME]); ++it) {
+
+ sat::Solvable pkg = it->satSolvable();
+ //MIL << "match " << package_id << " " << pkg << endl;
+
+ if (want_source && !isKind<SrcPackage>(pkg)) {
+ //MIL << "not a src package\n";
+ continue;
+ }
+
+ if (!want_source && (isKind<SrcPackage>(pkg) || g_strcmp0 (pkg.arch().c_str(), arch))) {
+ //MIL << "not a matching arch\n";
+ continue;
+ }
+
+ const string &ver = pkg.edition ().asString();
+ if (g_strcmp0 (ver.c_str (), id_parts[PK_PACKAGE_ID_VERSION])) {
+ //MIL << "not a matching version\n";
+ continue;
+ }
+
+ if (!pkg.isSystem()) {
+ if (!strncmp(id_parts[PK_PACKAGE_ID_DATA], "installed", 9)) {
+ //MIL << "pkg is not installed\n";
+ continue;
+ }
+ if (g_strcmp0(pkg.repository().alias().c_str(), id_parts[PK_PACKAGE_ID_DATA])) {
+ //MIL << "repo does not match\n";
+ continue;
+ }
+ } else if (strncmp(id_parts[PK_PACKAGE_ID_DATA], "installed", 9)) {
+ //MIL << "pkg installed\n";
+ continue;
+ }
+
+ MIL << "found " << pkg << endl;
+ package = pkg;
+ break;
+ }
+
+ g_strfreev (id_parts);
+ return package;
+}
+
+RepoInfo
+zypp_get_Repository (PkBackendJob *job, const gchar *alias)
+{
+ RepoInfo info;
+
+ try {
+ RepoManager manager;
+ info = manager.getRepositoryInfo (alias);
+ } catch (const repo::RepoNotFoundException &ex) {
+ pk_backend_job_error_code (job, PK_ERROR_ENUM_REPO_NOT_FOUND, ex.asUserString().c_str() );
+ return RepoInfo ();
+ }
+
+ return info;
+}
+
+/*
+ * PK requires a transaction (backend method call) to abort immediately
+ * after an error is set. Unfortunately, zypp's 'refresh' methods call
+ * these signature methods on errors - and provide no way to signal an
+ * abort - instead the refresh continuing on with the next repository.
+ * PK (pk_backend_error_timeout_delay_cb) uses this as an excuse to
+ * abort the (still running) transaction, and to start another - which
+ * leads to multi-threaded use of zypp and hence sudden, random death.
+ *
+ * To cure this, we throw this custom exception across zypp and catch
+ * it outside (hopefully) the only entry point (zypp_refresh_meta_and_cache)
+ * that can cause these (zypp_signature_required) methods to be called.
+ *
+ */
+class AbortTransactionException {
+ public:
+ AbortTransactionException() {}
+};
+
+/**
+ * helper to refresh a repo's metadata and cache, catching signature
+ * exceptions in a safe way.
+ */
+static gboolean
+zypp_refresh_meta_and_cache (RepoManager &manager, RepoInfo &repo, bool force = false)
+{
+ try {
+ if (manager.checkIfToRefreshMetadata (repo, repo.url()) //RepoManager::RefreshIfNeededIgnoreDelay)
+ != RepoManager::REFRESH_NEEDED)
+ return TRUE;
+
+ sat::Pool pool = sat::Pool::instance ();
+ // Erase old solv file
+ pool.reposErase (repo.alias ());
+ manager.refreshMetadata (repo, force ?
+ RepoManager::RefreshForced :
+ RepoManager::RefreshIfNeededIgnoreDelay);
+ manager.buildCache (repo, force ?
+ RepoManager::BuildForced :
+ RepoManager::BuildIfNeeded);
+ manager.loadFromCache (repo);
+ return TRUE;
+ } catch (const AbortTransactionException &ex) {
+ return FALSE;
+ }
+}
+
+
+static gboolean
+system_and_package_are_x86 (sat::Solvable item)
+{
+ // i586, i686, ... all should be considered the same arch for our comparison
+ return ( item.arch() == Arch_i586 && ZConfig::defaultSystemArchitecture() == Arch_i686 );
+}
+
+static gboolean
+zypp_package_is_devel (const sat::Solvable &item)
+{
+ const string &name = item.name();
+ const char *cstr = name.c_str();
+
+ return ( g_str_has_suffix (cstr, "-debuginfo") ||
+ g_str_has_suffix (cstr, "-debugsource") ||
+ g_str_has_suffix (cstr, "-devel") );
+}
+
+/**
+ * should we omit a solvable from a result because of filtering ?
+ */
+static gboolean
+zypp_filter_solvable (PkBitfield filters, const sat::Solvable &item)
+{
+ // iterate through the given filters
+ if (!filters)
+ return FALSE;
+
+ for (guint i = 0; i < PK_FILTER_ENUM_LAST; i++) {
+ if ((filters & pk_bitfield_value (i)) == 0)
+ continue;
+ if (i == PK_FILTER_ENUM_INSTALLED && !(item.isSystem ()))
+ return TRUE;
+ if (i == PK_FILTER_ENUM_NOT_INSTALLED && item.isSystem ())
+ return TRUE;
+ if (i == PK_FILTER_ENUM_ARCH) {
+ if (item.arch () != ZConfig::defaultSystemArchitecture () &&
+ item.arch () != Arch_noarch &&
+ ! system_and_package_are_x86 (item))
+ return TRUE;
+ }
+ if (i == PK_FILTER_ENUM_NOT_ARCH) {
+ if (item.arch () == ZConfig::defaultSystemArchitecture () ||
+ system_and_package_are_x86 (item))
+ return TRUE;
+ }
+ if (i == PK_FILTER_ENUM_SOURCE && !(isKind<SrcPackage>(item)))
+ return TRUE;
+ if (i == PK_FILTER_ENUM_NOT_SOURCE && isKind<SrcPackage>(item))
+ return TRUE;
+ if (i == PK_FILTER_ENUM_DEVELOPMENT && !zypp_package_is_devel (item))
+ return TRUE;
+ if (i == PK_FILTER_ENUM_NOT_DEVELOPMENT && zypp_package_is_devel (item))
+ return TRUE;
+
+ // FIXME: add more enums - cf. libzif logic and pk-enum.h
+ // PK_FILTER_ENUM_SUPPORTED,
+ // PK_FILTER_ENUM_NOT_SUPPORTED,
+ }
+
+ return FALSE;
+}
+
+/**
+ * helper to emit pk package signals for a backend for a zypp solvable
+ */
+static void
+zypp_backend_package (PkBackendJob *job, PkInfoEnum info,
+ const sat::Solvable &pkg,
+ const char *opt_summary)
+{
+ gchar *id = zypp_build_package_id_from_resolvable (pkg);
+ pk_backend_job_package (job, info, id, opt_summary);
+ g_free (id);
+}
-#include <zypp/base/Logger.h>
-#include <zypp/ZYppFactory.h>
-#include <zypp/ResObject.h>
-#include <zypp/ResPoolProxy.h>
-#include <zypp/ui/Selectable.h>
-#include <zypp/Patch.h>
-#include <zypp/Package.h>
-#include <zypp/SrcPackage.h>
-#include <zypp/Pattern.h>
-#include <zypp/Product.h>
-#include <zypp/Repository.h>
-#include <zypp/RepoManager.h>
-#include <zypp/RepoInfo.h>
-#include <zypp/repo/RepoException.h>
-#include <zypp/parser/ParseException.h>
-#include <zypp/Pathname.h>
-#include <zypp/RelCompare.h>
-#include <zypp/ResFilters.h>
-#include <zypp/base/Algorithm.h>
-#include <zypp/target/rpm/RpmDb.h>
-#include <zypp/target/rpm/RpmHeader.h>
-#include <zypp/target/rpm/RpmException.h>
-#include <zypp/base/Functional.h>
-#include <zypp/parser/ProductFileReader.h>
-#include <zypp/TmpPath.h>
-#include <zypp/PathInfo.h>
-#include <zypp/repo/PackageProvider.h>
-#include <zypp/repo/SrcPackageProvider.h>
+/*
+ * Emit signals for the packages, -but- if we have an installed package
+ * we don't notify the client that the package is also available, since
+ * PK doesn't handle re-installs (by some quirk).
+ */
+void
+zypp_emit_filtered_packages_in_list (PkBackendJob *job, PkBitfield filters, const vector<sat::Solvable> &v)
+{
+ typedef vector<sat::Solvable>::const_iterator sat_it_t;
-#include <zypp/sat/Solvable.h>
+ vector<sat::Solvable> installed;
-#include "pk-backend-zypp-private.h"
+ // always emit system installed packages first
+ for (sat_it_t it = v.begin (); it != v.end (); ++it) {
+ if (!it->isSystem() ||
+ zypp_filter_solvable (filters, *it))
+ continue;
-#include "zypp-utils.h"
-#include "zypp-events.h"
+ zypp_backend_package (job, PK_INFO_ENUM_INSTALLED, *it,
+ make<ResObject>(*it)->summary().c_str());
+ installed.push_back (*it);
+ }
-using namespace std;
-using namespace zypp;
+ // then available packages later
+ for (sat_it_t it = v.begin (); it != v.end (); ++it) {
+ gboolean match;
-PkBackendZYppPrivate *priv = 0L;
+ if (it->isSystem() ||
+ zypp_filter_solvable (filters, *it))
+ continue;
-enum PkgSearchType {
- SEARCH_TYPE_NAME = 0,
- SEARCH_TYPE_DETAILS = 1,
- SEARCH_TYPE_FILE = 2,
- SEARCH_TYPE_RESOLVE = 3
-};
+ match = FALSE;
+ for (sat_it_t i = installed.begin (); !match && i != installed.end (); i++) {
+ match = it->sameNVRA (*i) &&
+ !(!isKind<SrcPackage>(*it) ^
+ !isKind<SrcPackage>(*i));
+ }
+ if (!match) {
+ zypp_backend_package (job, PK_INFO_ENUM_AVAILABLE, *it,
+ make<ResObject>(*it)->summary().c_str());
+ }
+ }
+}
-// helper function to restore the pool status
-// after doing operations on it
-class PoolStatusSaver : private base::NonCopyable
+
+
+/**
+ * Returns a set of all packages the could be updated
+ * (you're able to exclude a single (normally the 'patch' repo)
+ */
+static void
+zypp_get_package_updates (string repo, set<PoolItem> &pks)
{
-public:
- PoolStatusSaver() {
- ResPool::instance().proxy().saveState();
+ ResPool pool = ResPool::instance ();
+
+ ResObject::Kind kind = ResTraits<Package>::kind;
+ ResPool::byKind_iterator it = pool.byKindBegin (kind);
+ ResPool::byKind_iterator e = pool.byKindEnd (kind);
+
+ getZYpp()->resolver()->doUpdate();
+ for (; it != e; ++it)
+ if (it->status().isToBeInstalled()) {
+ ui::Selectable::constPtr s =
+ ui::Selectable::get((*it)->kind(), (*it)->name());
+ if (s->hasInstalledObj())
+ pks.insert(*it);
+ }
+}
+
+/**
+ * Returns a set of all patches the could be installed
+ */
+static void
+zypp_get_patches (PkBackendJob *job, ZYpp::Ptr zypp, set<PoolItem> &patches)
+{
+ _updating_self = FALSE;
+
+ zypp->resolver ()->setIgnoreAlreadyRecommended (TRUE);
+ zypp->resolver ()->resolvePool ();
+
+ for (ResPoolProxy::const_iterator it = zypp->poolProxy ().byKindBegin<Patch>();
+ it != zypp->poolProxy ().byKindEnd<Patch>(); it ++) {
+ // check if the patch is needed and not set to taboo
+ if((*it)->isNeeded() && !((*it)->candidateObj ().isUnwanted())) {
+ Patch::constPtr patch = asKind<Patch>((*it)->candidateObj ().resolvable ());
+ if (_updating_self) {
+ if (patch->restartSuggested ())
+ patches.insert ((*it)->candidateObj ());
+ }
+ else
+ patches.insert ((*it)->candidateObj ());
+
+ // check if the patch updates libzypp or packageKit and show only these
+ if (!_updating_self && patch->restartSuggested ()) {
+ _updating_self = TRUE;
+ patches.clear ();
+ patches.insert ((*it)->candidateObj ());
+ }
+ }
+
}
+}
- ~PoolStatusSaver() {
- ResPool::instance().proxy().restoreState();
+/**
+ * Return the best, most friendly selection of update patches and packages that
+ * we can find. Also manages _updating_self to prioritise critical infrastructure
+ * updates.
+ */
+static void
+zypp_get_updates (PkBackendJob *job, ZYpp::Ptr zypp, set<PoolItem> &candidates)
+{
+ typedef set<PoolItem>::iterator pi_it_t;
+ zypp_get_patches (job, zypp, candidates);
+
+ if (!_updating_self) {
+ // exclude the patch-repository
+ string patchRepo;
+ if (!candidates.empty ()) {
+ patchRepo = candidates.begin ()->resolvable ()->repoInfo ().alias ();
+ }
+
+ bool hidePackages = false;
+ if (PathInfo("/etc/PackageKit/ZYpp.conf").isExist()) {
+ parser::IniDict vendorConf(InputStream("/etc/PackageKit/ZYpp.conf"));
+ if (vendorConf.hasSection("Updates")) {
+ for ( parser::IniDict::entry_const_iterator eit = vendorConf.entriesBegin("Updates");
+ eit != vendorConf.entriesEnd("Updates");
+ ++eit )
+ {
+ if ((*eit).first == "HidePackages" &&
+ str::strToTrue((*eit).second))
+ hidePackages = true;
+ }
+ }
+ }
+
+ if (!hidePackages)
+ {
+ set<PoolItem> packages;
+ zypp_get_package_updates(patchRepo, packages);
+
+ pi_it_t cb = candidates.begin (), ce = candidates.end (), ci;
+ for (ci = cb; ci != ce; ++ci) {
+ if (!isKind<Patch>(ci->resolvable()))
+ continue;
+
+ Patch::constPtr patch = asKind<Patch>(ci->resolvable());
+
+ // Remove contained packages from list of packages to add
+ sat::SolvableSet::const_iterator pki;
+ Patch::Contents content(patch->contents());
+ for (pki = content.begin(); pki != content.end(); ++pki) {
+
+ pi_it_t pb = packages.begin (), pe = packages.end (), pi;
+ for (pi = pb; pi != pe; ++pi) {
+ if (pi->satSolvable() == sat::Solvable::noSolvable)
+ continue;
+
+ if (pi->satSolvable().identical (*pki)) {
+ packages.erase (pi);
+ break;
+ }
+ }
+ }
+ }
+
+ // merge into the list
+ candidates.insert (packages.begin (), packages.end ());
+ }
}
-};
+}
+
+/**
+ * Sets the restart flag of a patch
+ */
+static void
+zypp_check_restart (PkRestartEnum *restart, Patch::constPtr patch)
+{
+ if (patch == NULL || restart == NULL)
+ return;
+
+ // set the restart flag if a restart is needed
+ if (*restart != PK_RESTART_ENUM_SYSTEM &&
+ ( patch->reloginSuggested () ||
+ patch->restartSuggested () ||
+ patch->rebootSuggested ()) ) {
+ if (patch->reloginSuggested () || patch->restartSuggested ())
+ *restart = PK_RESTART_ENUM_SESSION;
+ if (patch->rebootSuggested ())
+ *restart = PK_RESTART_ENUM_SYSTEM;
+ }
+}
+
+/**
+ * helper to emit pk package status signals based on a ResPool object
+ */
+static bool
+zypp_backend_pool_item_notify (PkBackendJob *job,
+ const PoolItem &item,
+ gboolean sanity_check = FALSE)
+{
+ PkInfoEnum status = PK_INFO_ENUM_UNKNOWN;
+
+ if (item.status ().isToBeUninstalledDueToUpgrade ()) {
+ MIL << "updating " << item << endl;
+ status = PK_INFO_ENUM_UPDATING;
+ } else if (item.status ().isToBeUninstalledDueToObsolete ()) {
+ status = PK_INFO_ENUM_OBSOLETING;
+ } else if (item.status ().isToBeInstalled ()) {
+ MIL << "installing " << item << endl;
+ status = PK_INFO_ENUM_INSTALLING;
+ } else if (item.status ().isToBeUninstalled ()) {
+ status = PK_INFO_ENUM_REMOVING;
+
+ const string &name = item.satSolvable().name();
+ if (name == "glibc" || name == "PackageKit" ||
+ name == "rpm" || name == "libzypp") {
+ pk_backend_job_error_code (job, PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE,
+ "The package %s is essential to correct operation and cannot be removed using this tool.",
+ name.c_str());
+ return false;
+ }
+ }
+
+ // FIXME: do we need more heavy lifting here cf. zypper's
+ // Summary.cc (readPool) to generate _DOWNGRADING types ?
+ if (status != PK_INFO_ENUM_UNKNOWN) {
+ const string &summary = item.resolvable ()->summary ();
+ zypp_backend_package (job, status, item.resolvable()->satSolvable(), summary.c_str ());
+ }
+ return true;
+}
+
+/**
+ * simulate, or perform changes in pool to the system
+ */
+static gboolean
+zypp_perform_execution (PkBackendJob *job, ZYpp::Ptr zypp, PerformType type, gboolean force, PkBitfield transaction_flags)
+{
+ MIL << force << " " << pk_filter_bitfield_to_string(transaction_flags) << endl;
+ gboolean ret = FALSE;
+
+ PkBackend *backend = PK_BACKEND(pk_backend_job_get_backend(job));
+
+ try {
+ if (force)
+ zypp->resolver ()->setForceResolve (force);
+
+ // Gather up any dependencies
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_DEP_RESOLVE);
+ zypp->resolver ()->setIgnoreAlreadyRecommended (TRUE);
+ if (!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;
+
+ 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 ())
+ it->statusReset ();
+ }
+
+ pk_backend_job_error_code (job, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, emsg);
+ g_free (emsg);
+
+ goto exit;
+ }
+
+ switch (type) {
+ case INSTALL:
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_INSTALL);
+ break;
+ case REMOVE:
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_REMOVE);
+ break;
+ case UPDATE:
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_UPDATE);
+ break;
+ }
+
+ ResPool pool = ResPool::instance ();
+ if (pk_bitfield_contain (transaction_flags, PK_TRANSACTION_FLAG_ENUM_SIMULATE)) {
+ ret = TRUE;
+
+ MIL << "simulating" << endl;
+
+ for (ResPool::const_iterator it = pool.begin (); it != pool.end (); ++it) {
+ if (type == REMOVE && !(*it)->isSystem ()) {
+ it->statusReset ();
+ continue;
+ }
+ // for updates we only care for updates
+ if (type == UPDATE && it->status ().isToBeUninstalledDueToUpgrade ())
+ continue;
+
+ if (!zypp_backend_pool_item_notify (job, *it, TRUE))
+ ret = FALSE;
+ it->statusReset ();
+ }
+ goto exit;
+ }
+
+
+ // look for licenses to confirm
+
+ for (ResPool::const_iterator it = pool.begin (); it != pool.end (); ++it) {
+ if (it->status ().isToBeInstalled () && !(it->resolvable()->licenseToConfirm().empty ())) {
+ gchar *eula_id = g_strdup ((*it)->name ().c_str ());
+ gboolean has_eula = pk_backend_is_eula_valid (backend, eula_id);
+ if (!has_eula) {
+ gchar *package_id = zypp_build_package_id_from_resolvable (it->satSolvable ());
+ pk_backend_job_eula_required (job,
+ eula_id,
+ package_id,
+ (*it)->vendor ().c_str (),
+ it->resolvable()->licenseToConfirm().c_str ());
+ pk_backend_job_error_code (job, PK_ERROR_ENUM_NO_LICENSE_AGREEMENT, "You've to agree/decline a license");
+ g_free (package_id);
+ g_free (eula_id);
+ goto exit;
+ }
+ g_free (eula_id);
+ }
+ }
+
+ // Perform the installation
+ gboolean only_download = pk_bitfield_contain (transaction_flags, PK_TRANSACTION_FLAG_ENUM_ONLY_DOWNLOAD);
+
+ ZYppCommitPolicy policy;
+ policy.restrictToMedia (0); // 0 == install all packages regardless to media
+ if (only_download)
+ policy.downloadMode(DownloadOnly);
+ else
+ policy.downloadMode (DownloadInHeaps);
+
+ policy.syncPoolAfterCommit (true);
+ if (!pk_bitfield_contain (transaction_flags, PK_TRANSACTION_FLAG_ENUM_ONLY_TRUSTED))
+ policy.rpmNoSignature(true);
+
+ ZYppCommitResult result = zypp->commit (policy);
+
+ bool worked = result.allDone();
+ if (only_download)
+ worked = result.noError();
+
+ if ( ! worked )
+ {
+ std::ostringstream todolist;
+ char separator = '\0';
+
+ // process all steps not DONE (ERROR and TODO)
+ const sat::Transaction & trans( result.transaction() );
+ for_( it, trans.actionBegin(~sat::Transaction::STEP_DONE), trans.actionEnd() )
+ {
+ if ( separator )
+ todolist << separator << it->ident();
+ else
+ {
+ todolist << it->ident();
+ separator = '\n';
+ }
+ }
+
+ pk_backend_job_error_code (job, PK_ERROR_ENUM_TRANSACTION_ERROR,
+ "Transaction could not be completed.\n Theses packages could not be installed: %s",
+ todolist.str().c_str());
+
+ goto exit;
+ }
+
+ ret = TRUE;
+ } catch (const repo::RepoNotFoundException &ex) {
+ pk_backend_job_error_code (job, PK_ERROR_ENUM_REPO_NOT_FOUND, ex.asUserString().c_str() );
+ } catch (const target::rpm::RpmException &ex) {
+ pk_backend_job_error_code (job, PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED, ex.asUserString().c_str () );
+ } catch (const Exception &ex) {
+ pk_backend_job_error_code (job, PK_ERROR_ENUM_INTERNAL_ERROR, ex.asUserString().c_str() );
+ }
+
+ exit:
+ /* reset the various options */
+ try {
+ zypp->resolver ()->setForceResolve (FALSE);
+ } catch (const Exception &ex) { /* we tried */ }
+
+ return ret;
+}
+
+/**
+ * build array of package_id's seperated by blanks out of the capabilities of a solvable
+ */
+static GPtrArray *
+zypp_build_package_id_capabilities (Capabilities caps, gboolean terminate = TRUE)
+{
+ GPtrArray *package_ids = g_ptr_array_new();
+
+ sat::WhatProvides provs (caps);
+
+ for (sat::WhatProvides::const_iterator it = provs.begin (); it != provs.end (); ++it) {
+ gchar *package_id = zypp_build_package_id_from_resolvable (*it);
+ g_ptr_array_add(package_ids, package_id);
+ }
+ if (terminate)
+ g_ptr_array_add(package_ids, NULL);
+ return package_ids;
+}
+
+/**
+ * refresh the enabled repositories
+ */
+static gboolean
+zypp_refresh_cache (PkBackendJob *job, ZYpp::Ptr zypp, gboolean force)
+{
+ MIL << force << endl;
+ // This call is needed as it calls initializeTarget which appears to properly setup the keyring
+
+ if (zypp == NULL)
+ return FALSE;
+ filesystem::Pathname pathname("/");
+ // This call is needed to refresh system rpmdb status while refresh cache
+ zypp->finishTarget ();
+ zypp->initializeTarget (pathname);
+
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_REFRESH_CACHE);
+ pk_backend_job_set_percentage (job, 0);
+
+ RepoManager manager;
+ list <RepoInfo> repos;
+ try
+ {
+ repos = list<RepoInfo>(manager.repoBegin(),manager.repoEnd());
+ }
+ catch ( const Exception &e)
+ {
+ // FIXME: make sure this dumps out the right sring.
+ pk_backend_job_error_code (job, PK_ERROR_ENUM_REPO_NOT_FOUND, e.asUserString().c_str() );
+ return FALSE;
+ }
+
+ int i = 1;
+ int num_of_repos = repos.size ();
+ gchar *repo_messages = NULL;
+
+ for (list <RepoInfo>::iterator it = repos.begin(); it != repos.end(); ++it, i++) {
+ RepoInfo repo (*it);
+
+ if (!zypp_is_valid_repo (job, repo))
+ return FALSE;
+ if (pk_backend_job_get_is_error_set (job))
+ break;
+
+ // skip disabled repos
+ if (repo.enabled () == false)
+ continue;
+
+ // do as zypper does
+ if (!force && !repo.autorefresh())
+ continue;
+
+ // skip changeable meda (DVDs and CDs). Without doing this,
+ // the disc would be required to be physically present.
+ if (zypp_is_changeable_media (*repo.baseUrlsBegin ()) == true)
+ continue;
+
+ try {
+ // Refreshing metadata
+ g_free (_repoName);
+ _repoName = g_strdup (repo.alias ().c_str ());
+ zypp_refresh_meta_and_cache (manager, repo, force);
+ } catch (const Exception &ex) {
+ if (repo_messages == NULL) {
+ repo_messages = g_strdup_printf ("%s: %s%s", repo.alias ().c_str (), ex.asUserString ().c_str (), "\n");
+ } else {
+ repo_messages = g_strdup_printf ("%s%s: %s%s", repo_messages, repo.alias ().c_str (), ex.asUserString ().c_str (), "\n");
+ }
+ if (repo_messages == NULL || !g_utf8_validate (repo_messages, -1, NULL))
+ repo_messages = g_strdup ("A repository could not be refreshed");
+ g_strdelimit (repo_messages, "\\\f\r\t", ' ');
+ continue;
+ }
+
+ // Update the percentage completed
+ pk_backend_job_set_percentage (job, i >= num_of_repos ? 100 : (100 * i) / num_of_repos);
+ }
+ if (repo_messages != NULL)
+ pk_backend_job_message (job, PK_MESSAGE_ENUM_CONNECTION_REFUSED, repo_messages);
+
+ g_free (repo_messages);
+ return TRUE;
+}
+
+/**
+ * helper to simplify returning errors
+ */
+static void
+zypp_backend_finished_error (PkBackendJob *job, PkErrorEnum err_code,
+ const char *format, ...)
+{
+ va_list args;
+ gchar *buffer;
+
+ /* sadly no _va variant for error code setting */
+ va_start (args, format);
+ buffer = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ pk_backend_job_error_code (job, err_code, "%s", buffer);
+
+ g_free (buffer);
+
+ pk_backend_job_finished (job);
+}
+
+
/**
* We do not pretend we're thread safe when all we do is having a huge mutex
@@ -2049,3 +3595,101 @@ pk_backend_stop_job (PkBackend *backend, PkBackendJob *job)
}
+/**
+ * Ask the User if it is OK to import an GPG-Key for a repo
+ */
+bool
+ZyppBackend::ZyppBackendReceiver::zypp_signature_required (const PublicKey &key)
+{
+ bool ok = false;
+
+ if (find (priv->signatures.begin (), priv->signatures.end (), key.id ()) == priv->signatures.end ()) {
+ RepoInfo info = zypp_get_Repository (_job, _repoName);
+ if (info.type () == repo::RepoType::NONE)
+ pk_backend_job_error_code (_job, PK_ERROR_ENUM_INTERNAL_ERROR,
+ "Repository unknown");
+ else {
+ pk_backend_job_repo_signature_required (_job,
+ "dummy;0.0.1;i386;data",
+ _repoName,
+ info.baseUrlsBegin ()->asString ().c_str (),
+ key.name ().c_str (),
+ key.id ().c_str (),
+ key.fingerprint ().c_str (),
+ key.created ().asString ().c_str (),
+ PK_SIGTYPE_ENUM_GPG);
+ pk_backend_job_error_code (_job, PK_ERROR_ENUM_GPG_FAILURE,
+ "Signature verification for Repository %s failed", _repoName);
+ }
+ throw AbortTransactionException();
+ } else
+ ok = true;
+
+ return ok;
+}
+
+/**
+ * Ask the User if it is OK to refresh the Repo while we don't know the key
+ */
+bool
+ZyppBackend::ZyppBackendReceiver::zypp_signature_required (const string &file, const string &id)
+{
+ bool ok = false;
+
+ if (find (priv->signatures.begin (), priv->signatures.end (), id) == priv->signatures.end ()) {
+ RepoInfo info = zypp_get_Repository (_job, _repoName);
+ if (info.type () == repo::RepoType::NONE)
+ pk_backend_job_error_code (_job, PK_ERROR_ENUM_INTERNAL_ERROR,
+ "Repository unknown");
+ else {
+ pk_backend_job_repo_signature_required (_job,
+ "dummy;0.0.1;i386;data",
+ _repoName,
+ info.baseUrlsBegin ()->asString ().c_str (),
+ id.c_str (),
+ id.c_str (),
+ "UNKNOWN",
+ "UNKNOWN",
+ PK_SIGTYPE_ENUM_GPG);
+ pk_backend_job_error_code (_job, PK_ERROR_ENUM_GPG_FAILURE,
+ "Signature verification for Repository %s failed", _repoName);
+ }
+ throw AbortTransactionException();
+ } else
+ ok = true;
+
+ return ok;
+}
+
+/**
+ * Ask the User if it is OK to refresh the Repo while we don't know the key, only its id which was never seen before
+ */
+bool
+ZyppBackend::ZyppBackendReceiver::zypp_signature_required (const string &file)
+{
+ bool ok = false;
+
+ if (find (priv->signatures.begin (), priv->signatures.end (), file) == priv->signatures.end ()) {
+ RepoInfo info = zypp_get_Repository (_job, _repoName);
+ if (info.type () == repo::RepoType::NONE)
+ pk_backend_job_error_code (_job, PK_ERROR_ENUM_INTERNAL_ERROR,
+ "Repository unknown");
+ else {
+ pk_backend_job_repo_signature_required (_job,
+ "dummy;0.0.1;i386;data",
+ _repoName,
+ info.baseUrlsBegin ()->asString ().c_str (),
+ "UNKNOWN",
+ file.c_str (),
+ "UNKNOWN",
+ "UNKNOWN",
+ PK_SIGTYPE_ENUM_GPG);
+ pk_backend_job_error_code (_job, PK_ERROR_ENUM_GPG_FAILURE,
+ "Signature verification for Repository %s failed", _repoName);
+ }
+ throw AbortTransactionException();
+ } else
+ ok = true;
+
+ return ok;
+}
diff --git a/backends/zypp/zypp-events.h b/backends/zypp/zypp-events.h
deleted file mode 100644
index 623ec77..0000000
--- a/backends/zypp/zypp-events.h
+++ /dev/null
@@ -1,425 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (c) 2007 Novell, Inc.
- * Copyright (c) 2007 Boyd Timothy <btimothy@gmail.com>
- * Copyright (c) 2007-2008 Stefan Haas <shaas@suse.de>
- * Copyright (c) 2007-2008 Scott Reeves <sreeves@novell.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef _ZYPP_EVENTS_H_
-#define _ZYPP_EVENTS_H_
-
-#include <stdio.h>
-#include <glib.h>
-#include <pk-backend.h>
-#include <zypp/ZYppCallbacks.h>
-#include <zypp/Digest.h>
-#include <zypp/KeyRing.h>
-
-#include "zypp-utils.h"
-
-/*
-typedef struct {
- PkBackend *backend;
- guint percentage;
-} PercentageData;
-
-static gboolean
-emit_sub_percentage (gpointer data)
-{
- PercentageData *pd = (PercentageData *)data;
- //pk_backend_set_sub_percentage (pd->backend, pd->percentage);
- free (pd);
- return FALSE;
-}
-*/
-
-namespace ZyppBackend
-{
-
-class ZyppBackendReceiver
-{
-public:
- PkBackendJob *_job;
- gchar *_package_id;
- guint _sub_percentage;
-
- ZyppBackendReceiver()
- {
- _job = NULL;
- _package_id = NULL;
- _sub_percentage = 0;
- }
-
- virtual void clear_package_id ()
- {
- if (_package_id != NULL) {
- g_free (_package_id);
- _package_id = NULL;
- }
- }
-
- inline void
- update_sub_percentage (guint percentage)
- {
- // Only emit a percentage if it's different from the last
- // percentage we emitted and it's divisible by ten. We
- // don't want to overload dbus/GUI. Also account for the
- // fact that libzypp may skip over a "divisible by ten"
- // value (i.e., 28, 29, 31, 32).
-
- MIL << percentage << " " << _sub_percentage << std::endl;
- if (percentage <= _sub_percentage)
- return;
-
- if (!_package_id) {
- MIL << "percentage without package" << std::endl;
- return;
- }
-
- if (percentage > 100) {
- MIL << "libzypp is silly" << std::endl;
- return;
- }
-
- _sub_percentage = percentage;
- pk_backend_job_set_item_progress(_job, _package_id, PK_STATUS_ENUM_UNKNOWN, _sub_percentage);
- }
-
- void
- reset_sub_percentage ()
- {
- _sub_percentage = 0;
- //pk_backend_set_sub_percentage (_backend, _sub_percentage);
- }
-
-protected:
- ~ZyppBackendReceiver() {} // or a public virtual one
-};
-
-struct InstallResolvableReportReceiver : public zypp::callback::ReceiveReport<zypp::target::rpm::InstallResolvableReport>, ZyppBackendReceiver
-{
- zypp::Resolvable::constPtr _resolvable;
- bool preparing;
- int last_value;
-
- virtual void start (zypp::Resolvable::constPtr resolvable)
- {
- clear_package_id ();
- _package_id = zypp_build_package_id_from_resolvable (resolvable->satSolvable ());
- MIL << resolvable << " " << _package_id << std::endl;
- gchar* summary = g_strdup(zypp::asKind<zypp::ResObject>(resolvable)->summary().c_str ());
- if (_package_id != NULL) {
- pk_backend_job_set_status (_job, PK_STATUS_ENUM_INSTALL);
- pk_backend_job_package (_job, PK_INFO_ENUM_INSTALLING, _package_id, summary);
- reset_sub_percentage ();
- }
- // first we prepare then we install
- preparing = true;
- last_value = 0;
- g_free (summary);
- }
-
- virtual bool progress (int value, zypp::Resolvable::constPtr resolvable)
- {
- // we need to have extra logic here as progress is reported twice
- // and PackageKit does not like percentages going back
- if (preparing && value < last_value)
- preparing = false;
- last_value = value;
- MIL << preparing << " " << value << " " << _package_id << std::endl;
- int perc = 0;
- if (preparing)
- perc = value * 30 / 100;
- else
- perc = 30 + value * 70 / 100;
- update_sub_percentage (perc);
- return true;
- }
-
- virtual Action problem (zypp::Resolvable::constPtr resolvable, Error error, const std::string &description, RpmLevel level)
- {
- //g_debug ("InstallResolvableReportReceiver::problem()");
- return ABORT;
- }
-
- virtual void finish (zypp::Resolvable::constPtr resolvable, Error error, const std::string &reason, RpmLevel level)
- {
- MIL << reason << " " << _package_id << " " << resolvable << std::endl;
- if (_package_id != NULL) {
- //pk_backend_job_package (_backend, PK_INFO_ENUM_INSTALLED, _package_id, "TODO: Put the package summary here if possible");
- clear_package_id ();
- }
- }
-};
-
-struct RemoveResolvableReportReceiver : public zypp::callback::ReceiveReport<zypp::target::rpm::RemoveResolvableReport>, ZyppBackendReceiver
-{
- zypp::Resolvable::constPtr _resolvable;
-
- virtual void start (zypp::Resolvable::constPtr resolvable)
- {
- clear_package_id ();
- _package_id = zypp_build_package_id_from_resolvable (resolvable->satSolvable ());
- if (_package_id != NULL) {
- pk_backend_job_set_status (_job, PK_STATUS_ENUM_REMOVE);
- pk_backend_job_package (_job, PK_INFO_ENUM_REMOVING, _package_id, "");
- reset_sub_percentage ();
- }
- }
-
- virtual bool progress (int value, zypp::Resolvable::constPtr resolvable)
- {
- update_sub_percentage (value);
- return true;
- }
-
- virtual Action problem (zypp::Resolvable::constPtr resolvable, Error error, const std::string &description)
- {
- pk_backend_job_error_code (_job, PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE, description.c_str ());
- return ABORT;
- }
-
- virtual void finish (zypp::Resolvable::constPtr resolvable, Error error, const std::string &reason)
- {
- if (_package_id != NULL) {
- pk_backend_job_package (_job, PK_INFO_ENUM_FINISHED, _package_id, "");
- clear_package_id ();
- }
- }
-};
-
-struct RepoProgressReportReceiver : public zypp::callback::ReceiveReport<zypp::ProgressReport>, ZyppBackendReceiver
-{
- virtual void start (const zypp::ProgressData &data)
- {
- g_debug ("_____________- RepoProgressReportReceiver::start()___________________");
- reset_sub_percentage ();
- }
-
- virtual bool progress (const zypp::ProgressData &data)
- {
- //fprintf (stderr, "\n\n----> RepoProgressReportReceiver::progress(), %s:%d\n\n", data.name().c_str(), (int)data.val());
- update_sub_percentage ((int)data.val ());
- return true;
- }
-
- virtual void finish (const zypp::ProgressData &data)
- {
- //fprintf (stderr, "\n\n----> RepoProgressReportReceiver::finish()\n\n");
- }
-};
-
-struct RepoReportReceiver : public zypp::callback::ReceiveReport<zypp::repo::RepoReport>, ZyppBackendReceiver
-{
- virtual void start (const zypp::ProgressData &data, const zypp::RepoInfo)
- {
- g_debug ("______________________ RepoReportReceiver::start()________________________");
- reset_sub_percentage ();
- }
-
- virtual bool progress (const zypp::ProgressData &data)
- {
- //fprintf (stderr, "\n\n----> RepoReportReceiver::progress(), %s:%d\n", data.name().c_str(), (int)data.val());
- update_sub_percentage ((int)data.val ());
- return true;
- }
-
- virtual void finish (zypp::Repository source, const std::string &task, zypp::repo::RepoReport::Error error, const std::string &reason)
- {
- //fprintf (stderr, "\n\n----> RepoReportReceiver::finish()\n");
- }
-};
-
-struct DownloadProgressReportReceiver : public zypp::callback::ReceiveReport<zypp::repo::DownloadResolvableReport>, ZyppBackendReceiver
-{
- virtual void start (zypp::Resolvable::constPtr resolvable, const zypp::Url &file)
- {
- MIL << resolvable << " " << file << std::endl;
- clear_package_id ();
- _package_id = zypp_build_package_id_from_resolvable (resolvable->satSolvable ());
- gchar* summary = g_strdup(zypp::asKind<zypp::ResObject>(resolvable)->summary().c_str ());
-
- fprintf (stderr, "DownloadProgressReportReceiver::start():%s --%s\n",
- g_strdup (file.asString().c_str()), _package_id);
- if (_package_id != NULL) {
- pk_backend_job_set_status (_job, PK_STATUS_ENUM_DOWNLOAD);
- pk_backend_job_package (_job, PK_INFO_ENUM_DOWNLOADING, _package_id, summary);
- reset_sub_percentage ();
- }
- g_free(summary);
- }
-
- virtual bool progress (int value, zypp::Resolvable::constPtr resolvable)
- {
- MIL << resolvable << " " << value << " " << _package_id << std::endl;
- update_sub_percentage (value);
- //pk_backend_job_set_speed (_job, static_cast<guint>(dbps_current));
- return true;
- }
-
- virtual void finish (zypp::Resolvable::constPtr resolvable, Error error, const std::string &konreason)
- {
- MIL << resolvable << " " << error << " " << _package_id << std::endl;
- update_sub_percentage (100);
- clear_package_id ();
- }
-};
-
-struct MediaChangeReportReceiver : public zypp::callback::ReceiveReport<zypp::media::MediaChangeReport>, ZyppBackendReceiver
-{
- virtual Action requestMedia (zypp::Url &url, unsigned mediaNr, const std::string &label, zypp::media::MediaChangeReport::Error error, const std::string &description, const std::vector<std::string> & devices, unsigned int &dev_current)
- {
- pk_backend_job_error_code (_job, PK_ERROR_ENUM_REPO_NOT_AVAILABLE, description.c_str ());
- // We've to abort here, because there is currently no feasible way to inform the user to insert/change media
- return ABORT;
- }
-};
-
-struct ProgressReportReceiver : public zypp::callback::ReceiveReport<zypp::ProgressReport>, ZyppBackendReceiver
-{
- virtual void start (const zypp::ProgressData &progress)
- {
- MIL << std::endl;
- reset_sub_percentage ();
- }
-
- virtual bool progress (const zypp::ProgressData &progress)
- {
- MIL << progress.val() << std::endl;
- update_sub_percentage ((int)progress.val ());
- return true;
- }
-
- virtual void finish (const zypp::ProgressData &progress)
- {
- MIL << progress.val() << std::endl;
- update_sub_percentage ((int)progress.val ());
- }
-};
-
-// These last two are called -only- from zypp_refresh_meta_and_cache
-// *if this is not true* - we will get un-caught Abort exceptions.
-
-struct KeyRingReportReceiver : public zypp::callback::ReceiveReport<zypp::KeyRingReport>, ZyppBackendReceiver
-{
- virtual zypp::KeyRingReport::KeyTrust askUserToAcceptKey (const zypp::PublicKey &key, const zypp::KeyContext &keycontext)
- {
- if (zypp_signature_required(_job, key))
- return KEY_TRUST_AND_IMPORT;
- return KEY_DONT_TRUST;
- }
-
- virtual bool askUserToAcceptUnsignedFile (const std::string &file, const zypp::KeyContext &keycontext)
- {
- return zypp_signature_required (_job, file);
- }
-
- virtual bool askUserToAcceptUnknownKey (const std::string &file, const std::string &id, const zypp::KeyContext &keycontext)
- {
- return zypp_signature_required(_job, file, id);
- }
-
- virtual bool askUserToAcceptVerificationFailed (const std::string &file, const zypp::PublicKey &key, const zypp::KeyContext &keycontext)
- {
- return zypp_signature_required(_job, key);
- }
-
-};
-
-struct DigestReportReceiver : public zypp::callback::ReceiveReport<zypp::DigestReport>, ZyppBackendReceiver
-{
- virtual bool askUserToAcceptNoDigest (const zypp::Pathname &file)
- {
- return zypp_signature_required(_job, file.asString ());
- }
-
- virtual bool askUserToAcceptUnknownDigest (const zypp::Pathname &file, const std::string &name)
- {
- pk_backend_job_error_code(_job, PK_ERROR_ENUM_GPG_FAILURE, "Repo: %s Digest: %s", file.c_str (), name.c_str ());
- return zypp_signature_required(_job, file.asString ());
- }
-
- virtual bool askUserToAcceptWrongDigest (const zypp::Pathname &file, const std::string &requested, const std::string &found)
- {
- pk_backend_job_error_code(_job, PK_ERROR_ENUM_GPG_FAILURE, "For repo %s %s is requested but %s was found!",
- file.c_str (), requested.c_str (), found.c_str ());
- return zypp_signature_required(_job, file.asString ());
- }
-};
-
-}; // namespace ZyppBackend
-
-class EventDirector
-{
- private:
- ZyppBackend::RepoReportReceiver _repoReport;
- ZyppBackend::RepoProgressReportReceiver _repoProgressReport;
- ZyppBackend::InstallResolvableReportReceiver _installResolvableReport;
- ZyppBackend::RemoveResolvableReportReceiver _removeResolvableReport;
- ZyppBackend::DownloadProgressReportReceiver _downloadProgressReport;
- ZyppBackend::KeyRingReportReceiver _keyRingReport;
- ZyppBackend::DigestReportReceiver _digestReport;
- ZyppBackend::MediaChangeReportReceiver _mediaChangeReport;
- ZyppBackend::ProgressReportReceiver _progressReport;
-
- public:
- EventDirector ()
- {
- _repoReport.connect ();
- _repoProgressReport.connect ();
- _installResolvableReport.connect ();
- _removeResolvableReport.connect ();
- _downloadProgressReport.connect ();
- _keyRingReport.connect ();
- _digestReport.connect ();
- _mediaChangeReport.connect ();
- _progressReport.connect ();
- }
-
- void setJob(PkBackendJob *job)
- {
- _repoReport._job = job;
- _repoProgressReport._job = job;
- _installResolvableReport._job = job;
- _removeResolvableReport._job = job;
- _downloadProgressReport._job = job;
- _keyRingReport._job = job;
- _digestReport._job = job;
- _mediaChangeReport._job = job;
- _progressReport._job = job;
- }
-
- ~EventDirector ()
- {
- _repoReport.disconnect ();
- _repoProgressReport.disconnect ();
- _installResolvableReport.disconnect ();
- _removeResolvableReport.disconnect ();
- _downloadProgressReport.disconnect ();
- _keyRingReport.disconnect ();
- _digestReport.disconnect ();
- _mediaChangeReport.disconnect ();
- _progressReport.disconnect ();
- }
-};
-
-
-#endif // _ZYPP_EVENTS_H_
-
diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
deleted file mode 100644
index 27bcbc4..0000000
--- a/backends/zypp/zypp-utils.cpp
+++ /dev/null
@@ -1,1222 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (c) 2007 Novell, Inc.
- * Copyright (c) 2007 Boyd Timothy <btimothy@gmail.com>
- * Copyright (c) 2007-2008 Stefan Haas <shaas@suse.de>
- * Copyright (c) 2007-2008 Scott Reeves <sreeves@novell.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <sstream>
-#include <stdlib.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <glib/gi18n.h>
-#include <zypp/ZYpp.h>
-#include <zypp/ZYppFactory.h>
-#include <zypp/RepoManager.h>
-#include <zypp/media/MediaManager.h>
-#include <zypp/Resolvable.h>
-#include <zypp/ResPool.h>
-#include <zypp/Repository.h>
-#include <zypp/RepoManager.h>
-#include <zypp/RepoInfo.h>
-#include <zypp/repo/RepoException.h>
-#include <zypp/target/rpm/RpmException.h>
-#include <zypp/parser/ParseException.h>
-#include <zypp/base/Algorithm.h>
-#include <zypp/Pathname.h>
-#include <zypp/Patch.h>
-#include <zypp/Package.h>
-#include <zypp/ui/Selectable.h>
-#include <zypp/sat/Pool.h>
-#include <zypp/target/rpm/RpmDb.h>
-#include <zypp/target/rpm/RpmHeader.h>
-#include <zypp/target/rpm/librpmDb.h>
-#include <zypp/base/LogControl.h>
-#include <zypp/base/String.h>
-#include <zypp/parser/IniDict.h>
-#include <zypp/PathInfo.h>
-
-#include <zypp/base/Logger.h>
-
-#include <pk-backend.h>
-#define I_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE
-#include <packagekit-glib2/packagekit.h>
-
-#include "pk-backend-zypp-private.h"
-#include "zypp-utils.h"
-
-gchar * _repoName;
-gboolean _updating_self = FALSE;
-
-using namespace std;
-using namespace zypp;
-using zypp::filesystem::PathInfo;
-
-extern PkBackendZYppPrivate *priv;
-
-ZyppJob::ZyppJob(PkBackendJob *job)
-{
- MIL << "locking zypp" << std::endl;
- pthread_mutex_lock(&priv->zypp_mutex);
-
- if (priv->currentJob) {
- MIL << "currentjob is already defined - highly impossible" << endl;
- }
-
- pk_backend_job_set_locked(job, true);
- priv->currentJob = job;
- priv->eventDirector.setJob(job);
-}
-
-ZyppJob::~ZyppJob()
-{
- if (priv->currentJob)
- pk_backend_job_set_locked(priv->currentJob, false);
- priv->currentJob = 0;
- priv->eventDirector.setJob(0);
- MIL << "unlocking zypp" << std::endl;
- pthread_mutex_unlock(&priv->zypp_mutex);
-}
-
-/**
- * Initialize Zypp (Factory method)
- */
-ZYpp::Ptr
-ZyppJob::get_zypp()
-{
- static gboolean initialized = FALSE;
- ZYpp::Ptr zypp = NULL;
-
- try {
- zypp = ZYppFactory::instance ().getZYpp ();
-
- /* TODO: we need to lifecycle manage this, detect changes
- in the requested 'root' etc. */
- if (!initialized) {
- filesystem::Pathname pathname("/");
- zypp->initializeTarget (pathname);
-
- initialized = TRUE;
- }
- } catch (const ZYppFactoryException &ex) {
- pk_backend_job_error_code (priv->currentJob, PK_ERROR_ENUM_FAILED_INITIALIZATION, ex.asUserString().c_str() );
- return NULL;
- } catch (const Exception &ex) {
- pk_backend_job_error_code (priv->currentJob, PK_ERROR_ENUM_INTERNAL_ERROR, ex.asUserString().c_str() );
- return NULL;
- }
-
- return zypp;
-}
-
-/**
- * Enable and rotate zypp logging
- */
-gboolean
-zypp_logging ()
-{
- gchar *file = g_strdup ("/var/log/pk_backend_zypp");
- gchar *file_old = g_strdup ("/var/log/pk_backend_zypp-1");
-
- if (g_file_test (file, G_FILE_TEST_EXISTS)) {
- struct stat buffer;
- g_stat (file, &buffer);
- // if the file is bigger than 10 MB rotate
- if ((guint)buffer.st_size > 10485760) {
- if (g_file_test (file_old, G_FILE_TEST_EXISTS))
- g_remove (file_old);
- g_rename (file, file_old);
- }
- }
-
- base::LogControl::instance ().logfile(file);
-
- g_free (file);
- g_free (file_old);
-
- return TRUE;
-}
-
-gboolean
-zypp_is_changeable_media (const Url &url)
-{
- gboolean is_cd = false;
- try {
- media::MediaManager mm;
- media::MediaAccessId id = mm.open (url);
- is_cd = mm.isChangeable (id);
- mm.close (id);
- } catch (const media::MediaException &e) {
- // TODO: Do anything about this?
- }
-
- return is_cd;
-}
-
-namespace {
- /// Helper finding pattern at end or embedded in name.
- /// E.g '-debug' in 'repo-debug' or 'repo-debug-update'
- inline bool
- name_ends_or_contains( const std::string & name_r, const std::string & pattern_r, const char sepchar_r = '-' )
- {
- if ( ! pattern_r.empty() )
- {
- for ( std::string::size_type pos = name_r.find( pattern_r );
- pos != std::string::npos;
- pos = name_r.find( pattern_r, pos + pattern_r.size() ) )
- {
- if ( pos + pattern_r.size() == name_r.size() // at end
- || name_r[pos + pattern_r.size()] == sepchar_r ) // embedded
- return true;
- }
- }
- return false;
- }
-}
-
-gboolean
-zypp_is_development_repo (RepoInfo repo)
-{
- return ( name_ends_or_contains( repo.alias(), "-debuginfo" )
- || name_ends_or_contains( repo.alias(), "-debug" )
- || name_ends_or_contains( repo.alias(), "-source" )
- || name_ends_or_contains( repo.alias(), "-development" ) );
-}
-
-gboolean
-zypp_is_valid_repo (PkBackendJob *job, RepoInfo repo)
-{
-
- if (repo.alias().empty()){
- pk_backend_job_error_code (job, PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR, "Repository has no or invalid repo name defined.\n", repo.alias ().c_str ());
- return FALSE;
- }
-
- if (!repo.url().isValid()){
- pk_backend_job_error_code (job, PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR, "%s: Repository has no or invalid url defined.\n", repo.alias ().c_str ());
- return FALSE;
- }
-
- return TRUE;
-}
-
-ResPool
-zypp_build_pool (ZYpp::Ptr zypp, gboolean include_local)
-{
- static gboolean repos_loaded = FALSE;
-
- // the target is loaded or unloaded on request
- if (include_local) {
- // FIXME have to wait for fix in zypp (repeated loading of target)
- if (sat::Pool::instance().reposFind( sat::Pool::systemRepoAlias() ).solvablesEmpty ())
- {
- // Add local resolvables
- Target_Ptr target = zypp->target ();
- target->load ();
- }
- } else {
- if (!sat::Pool::instance().reposFind( sat::Pool::systemRepoAlias() ).solvablesEmpty ())
- {
- // Remove local resolvables
- Repository repository = sat::Pool::instance ().reposFind (sat::Pool::systemRepoAlias());
- repository.eraseFromPool ();
- }
- }
-
- // we only load repositories once.
- if (repos_loaded)
- return zypp->pool();
-
- // Add resolvables from enabled repos
- RepoManager manager;
- try {
- for (RepoManager::RepoConstIterator it = manager.repoBegin(); it != manager.repoEnd(); ++it) {
- RepoInfo repo (*it);
-
- // skip disabled repos
- if (repo.enabled () == false)
- continue;
- // skip not cached repos
- if (manager.isCached (repo) == false) {
- g_warning ("%s is not cached! Do a refresh", repo.alias ().c_str ());
- continue;
- }
- //FIXME see above, skip already cached repos
- if (sat::Pool::instance().reposFind( repo.alias ()) == Repository::noRepository)
- manager.loadFromCache (repo);
-
- }
- repos_loaded = true;
- } catch (const repo::RepoNoAliasException &ex) {
- g_error ("Can't figure an alias to look in cache");
- } catch (const repo::RepoNotCachedException &ex) {
- g_error ("The repo has to be cached at first: %s", ex.asUserString ().c_str ());
- } catch (const Exception &ex) {
- g_error ("TODO: Handle exceptions: %s", ex.asUserString ().c_str ());
- }
-
- return zypp->pool ();
-}
-
-void
-warn_outdated_repos(PkBackendJob *job, const ResPool & pool)
-{
- Repository repoobj;
- ResPool::repository_iterator it;
- for ( it = pool.knownRepositoriesBegin();
- it != pool.knownRepositoriesEnd();
- ++it )
- {
- Repository repo(*it);
- if ( repo.maybeOutdated() )
- {
- // warn the user
- pk_backend_job_message (job,
- PK_MESSAGE_ENUM_BROKEN_MIRROR,
- str::form("The repository %s seems to be outdated. You may want to try another mirror.",
- repo.alias().c_str()).c_str() );
- }
- }
-}
-
-target::rpm::RpmHeader::constPtr
-zypp_get_rpmHeader (const string &name, Edition edition)
-{
- target::rpm::librpmDb::db_const_iterator it;
- target::rpm::RpmHeader::constPtr result = new target::rpm::RpmHeader ();
-
- for (it.findPackage (name, edition); *it; ++it) {
- result = *it;
- }
-
- return result;
-}
-
-PkGroupEnum
-get_enum_group (const string &group_)
-{
- string group(str::toLower(group_));
-
- if (group.find ("amusements") != string::npos) {
- return PK_GROUP_ENUM_GAMES;
- } else if (group.find ("development") != string::npos) {
- return PK_GROUP_ENUM_PROGRAMMING;
- } else if (group.find ("hardware") != string::npos) {
- return PK_GROUP_ENUM_SYSTEM;
- } else if (group.find ("archiving") != string::npos
- || group.find("clustering") != string::npos
- || group.find("system/monitoring") != string::npos
- || group.find("databases") != string::npos
- || group.find("system/management") != string::npos) {
- return PK_GROUP_ENUM_ADMIN_TOOLS;
- } else if (group.find ("graphics") != string::npos) {
- return PK_GROUP_ENUM_GRAPHICS;
- } else if (group.find ("multimedia") != string::npos) {
- return PK_GROUP_ENUM_MULTIMEDIA;
- } else if (group.find ("network") != string::npos) {
- return PK_GROUP_ENUM_NETWORK;
- } else if (group.find ("office") != string::npos
- || group.find("text") != string::npos
- || group.find("editors") != string::npos) {
- return PK_GROUP_ENUM_OFFICE;
- } else if (group.find ("publishing") != string::npos) {
- return PK_GROUP_ENUM_PUBLISHING;
- } else if (group.find ("security") != string::npos) {
- return PK_GROUP_ENUM_SECURITY;
- } else if (group.find ("telephony") != string::npos) {
- return PK_GROUP_ENUM_COMMUNICATION;
- } else if (group.find ("gnome") != string::npos) {
- return PK_GROUP_ENUM_DESKTOP_GNOME;
- } else if (group.find ("kde") != string::npos) {
- return PK_GROUP_ENUM_DESKTOP_KDE;
- } else if (group.find ("xfce") != string::npos) {
- return PK_GROUP_ENUM_DESKTOP_XFCE;
- } else if (group.find ("gui/other") != string::npos) {
- return PK_GROUP_ENUM_DESKTOP_OTHER;
- } else if (group.find ("localization") != string::npos) {
- return PK_GROUP_ENUM_LOCALIZATION;
- } else if (group.find ("system") != string::npos) {
- return PK_GROUP_ENUM_SYSTEM;
- } else if (group.find ("scientific") != string::npos) {
- return PK_GROUP_ENUM_EDUCATION;
- }
-
- return PK_GROUP_ENUM_UNKNOWN;
-}
-
-void
-zypp_get_packages_by_name (const gchar *package_name,
- const ResKind kind,
- vector<sat::Solvable> &result,
- gboolean include_local)
-{
- ui::Selectable::Ptr sel( ui::Selectable::get( kind, package_name ) );
- if ( sel ) {
- if ( ! sel->installedEmpty() ) {
- for_( it, sel->installedBegin(), sel->installedEnd() )
- result.push_back( (*it).satSolvable() );
- }
- if ( ! sel->availableEmpty() ) {
- for_( it, sel->availableBegin(), sel->availableEnd() )
- result.push_back( (*it).satSolvable() );
- }
- }
-}
-
-void
-zypp_get_packages_by_file (ZYpp::Ptr zypp,
- const gchar *search_file,
- vector<sat::Solvable> &ret)
-{
- ResPool pool = zypp_build_pool (zypp, TRUE);
-
- string file (search_file);
-
- target::rpm::librpmDb::db_const_iterator it;
- target::rpm::RpmHeader::constPtr result = new target::rpm::RpmHeader ();
-
- for (it.findByFile (search_file); *it; ++it) {
- for (ResPool::byName_iterator it2 = pool.byNameBegin (it->tag_name ()); it2 != pool.byNameEnd (it->tag_name ()); it2++) {
- if ((*it2)->isSystem ())
- ret.push_back ((*it2)->satSolvable ());
- }
- }
-
- if (ret.empty ()) {
- Capability cap (search_file);
- sat::WhatProvides prov (cap);
-
- for(sat::WhatProvides::const_iterator it = prov.begin (); it != prov.end (); ++it) {
- ret.push_back (*it);
- }
- }
-}
-
-// gnome-packagekit;3.6.1-132.1;x86_64;G:F
-sat::Solvable
-zypp_get_package_by_id (const gchar *package_id)
-{
- MIL << package_id << endl;
- if (!pk_package_id_check(package_id)) {
- // TODO: Do we need to do something more for this error?
- return sat::Solvable::noSolvable;
- }
-
- gchar **id_parts = pk_package_id_split(package_id);
- const gchar *arch = id_parts[PK_PACKAGE_ID_ARCH];
- if (!arch)
- arch = "noarch";
- bool want_source = !g_strcmp0 (arch, "source");
-
- sat::Solvable package;
-
- ResPool pool = ResPool::instance();
-
- // Iterate over the resolvables and mark the one we want to check its dependencies
- for (ResPool::byName_iterator it = pool.byNameBegin (id_parts[PK_PACKAGE_ID_NAME]);
- it != pool.byNameEnd (id_parts[PK_PACKAGE_ID_NAME]); ++it) {
-
- sat::Solvable pkg = it->satSolvable();
- //MIL << "match " << package_id << " " << pkg << endl;
-
- if (want_source && !isKind<SrcPackage>(pkg)) {
- //MIL << "not a src package\n";
- continue;
- }
-
- if (!want_source && (isKind<SrcPackage>(pkg) || g_strcmp0 (pkg.arch().c_str(), arch))) {
- //MIL << "not a matching arch\n";
- continue;
- }
-
- const string &ver = pkg.edition ().asString();
- if (g_strcmp0 (ver.c_str (), id_parts[PK_PACKAGE_ID_VERSION])) {
- //MIL << "not a matching version\n";
- continue;
- }
-
- if (!pkg.isSystem()) {
- if (!strncmp(id_parts[PK_PACKAGE_ID_DATA], "installed", 9)) {
- //MIL << "pkg is not installed\n";
- continue;
- }
- if (g_strcmp0(pkg.repository().alias().c_str(), id_parts[PK_PACKAGE_ID_DATA])) {
- //MIL << "repo does not match\n";
- continue;
- }
- } else if (strncmp(id_parts[PK_PACKAGE_ID_DATA], "installed", 9)) {
- //MIL << "pkg installed\n";
- continue;
- }
-
- MIL << "found " << pkg << endl;
- package = pkg;
- break;
- }
-
- g_strfreev (id_parts);
- return package;
-}
-
-RepoInfo
-zypp_get_Repository (PkBackendJob *job, const gchar *alias)
-{
- RepoInfo info;
-
- try {
- RepoManager manager;
- info = manager.getRepositoryInfo (alias);
- } catch (const repo::RepoNotFoundException &ex) {
- pk_backend_job_error_code (job, PK_ERROR_ENUM_REPO_NOT_FOUND, ex.asUserString().c_str() );
- return RepoInfo ();
- }
-
- return info;
-}
-
-/*
- * PK requires a transaction (backend method call) to abort immediately
- * after an error is set. Unfortunately, zypp's 'refresh' methods call
- * these signature methods on errors - and provide no way to signal an
- * abort - instead the refresh continuing on with the next repository.
- * PK (pk_backend_error_timeout_delay_cb) uses this as an excuse to
- * abort the (still running) transaction, and to start another - which
- * leads to multi-threaded use of zypp and hence sudden, random death.
- *
- * To cure this, we throw this custom exception across zypp and catch
- * it outside (hopefully) the only entry point (zypp_refresh_meta_and_cache)
- * that can cause these (zypp_signature_required) methods to be called.
- *
- */
-class AbortTransactionException {
- public:
- AbortTransactionException() {}
-};
-
-gboolean
-zypp_refresh_meta_and_cache (RepoManager &manager, RepoInfo &repo, bool force)
-{
- try {
- if (manager.checkIfToRefreshMetadata (repo, repo.url()) //RepoManager::RefreshIfNeededIgnoreDelay)
- != RepoManager::REFRESH_NEEDED)
- return TRUE;
-
- sat::Pool pool = sat::Pool::instance ();
- // Erase old solv file
- pool.reposErase (repo.alias ());
- manager.refreshMetadata (repo, force ?
- RepoManager::RefreshForced :
- RepoManager::RefreshIfNeededIgnoreDelay);
- manager.buildCache (repo, force ?
- RepoManager::BuildForced :
- RepoManager::BuildIfNeeded);
- manager.loadFromCache (repo);
- return TRUE;
- } catch (const AbortTransactionException &ex) {
- return FALSE;
- }
-}
-
-gboolean
-zypp_signature_required (PkBackendJob *job, const PublicKey &key)
-{
- gboolean ok = FALSE;
-
- if (find (priv->signatures.begin (), priv->signatures.end (), key.id ()) == priv->signatures.end ()) {
- RepoInfo info = zypp_get_Repository (job, _repoName);
- if (info.type () == repo::RepoType::NONE)
- pk_backend_job_error_code (job, PK_ERROR_ENUM_INTERNAL_ERROR,
- "Repository unknown");
- else {
- pk_backend_job_repo_signature_required (job,
- "dummy;0.0.1;i386;data",
- _repoName,
- info.baseUrlsBegin ()->asString ().c_str (),
- key.name ().c_str (),
- key.id ().c_str (),
- key.fingerprint ().c_str (),
- key.created ().asString ().c_str (),
- PK_SIGTYPE_ENUM_GPG);
- pk_backend_job_error_code (job, PK_ERROR_ENUM_GPG_FAILURE,
- "Signature verification for Repository %s failed", _repoName);
- }
- throw AbortTransactionException();
- } else
- ok = TRUE;
-
- return ok;
-}
-
-gboolean
-zypp_signature_required (PkBackendJob *job, const string &file, const string &id)
-{
- gboolean ok = FALSE;
-
- if (find (priv->signatures.begin (), priv->signatures.end (), id) == priv->signatures.end ()) {
- RepoInfo info = zypp_get_Repository (job, _repoName);
- if (info.type () == repo::RepoType::NONE)
- pk_backend_job_error_code (job, PK_ERROR_ENUM_INTERNAL_ERROR,
- "Repository unknown");
- else {
- pk_backend_job_repo_signature_required (job,
- "dummy;0.0.1;i386;data",
- _repoName,
- info.baseUrlsBegin ()->asString ().c_str (),
- id.c_str (),
- id.c_str (),
- "UNKNOWN",
- "UNKNOWN",
- PK_SIGTYPE_ENUM_GPG);
- pk_backend_job_error_code (job, PK_ERROR_ENUM_GPG_FAILURE,
- "Signature verification for Repository %s failed", _repoName);
- }
- throw AbortTransactionException();
- } else
- ok = TRUE;
-
- return ok;
-}
-
-gboolean
-zypp_signature_required (PkBackendJob *job, const string &file)
-{
- gboolean ok = FALSE;
-
- if (find (priv->signatures.begin (), priv->signatures.end (), file) == priv->signatures.end ()) {
- RepoInfo info = zypp_get_Repository (job, _repoName);
- if (info.type () == repo::RepoType::NONE)
- pk_backend_job_error_code (job, PK_ERROR_ENUM_INTERNAL_ERROR,
- "Repository unknown");
- else {
- pk_backend_job_repo_signature_required (job,
- "dummy;0.0.1;i386;data",
- _repoName,
- info.baseUrlsBegin ()->asString ().c_str (),
- "UNKNOWN",
- file.c_str (),
- "UNKNOWN",
- "UNKNOWN",
- PK_SIGTYPE_ENUM_GPG);
- pk_backend_job_error_code (job, PK_ERROR_ENUM_GPG_FAILURE,
- "Signature verification for Repository %s failed", _repoName);
- }
- throw AbortTransactionException();
- } else
- ok = TRUE;
-
- return ok;
-}
-
-gboolean
-system_and_package_are_x86 (sat::Solvable item)
-{
- // i586, i686, ... all should be considered the same arch for our comparison
- return ( item.arch() == Arch_i586 && ZConfig::defaultSystemArchitecture() == Arch_i686 );
-}
-
-static gboolean
-zypp_package_is_devel (const sat::Solvable &item)
-{
- const string &name = item.name();
- const char *cstr = name.c_str();
-
- return ( g_str_has_suffix (cstr, "-debuginfo") ||
- g_str_has_suffix (cstr, "-debugsource") ||
- g_str_has_suffix (cstr, "-devel") );
-}
-
-/* should we filter out this package ? */
-gboolean
-zypp_filter_solvable (PkBitfield filters, const sat::Solvable &item)
-{
- // iterate through the given filters
- if (!filters)
- return FALSE;
-
- for (guint i = 0; i < PK_FILTER_ENUM_LAST; i++) {
- if ((filters & pk_bitfield_value (i)) == 0)
- continue;
- if (i == PK_FILTER_ENUM_INSTALLED && !(item.isSystem ()))
- return TRUE;
- if (i == PK_FILTER_ENUM_NOT_INSTALLED && item.isSystem ())
- return TRUE;
- if (i == PK_FILTER_ENUM_ARCH) {
- if (item.arch () != ZConfig::defaultSystemArchitecture () &&
- item.arch () != Arch_noarch &&
- ! system_and_package_are_x86 (item))
- return TRUE;
- }
- if (i == PK_FILTER_ENUM_NOT_ARCH) {
- if (item.arch () == ZConfig::defaultSystemArchitecture () ||
- system_and_package_are_x86 (item))
- return TRUE;
- }
- if (i == PK_FILTER_ENUM_SOURCE && !(isKind<SrcPackage>(item)))
- return TRUE;
- if (i == PK_FILTER_ENUM_NOT_SOURCE && isKind<SrcPackage>(item))
- return TRUE;
- if (i == PK_FILTER_ENUM_DEVELOPMENT && !zypp_package_is_devel (item))
- return TRUE;
- if (i == PK_FILTER_ENUM_NOT_DEVELOPMENT && zypp_package_is_devel (item))
- return TRUE;
-
- // FIXME: add more enums - cf. libzif logic and pk-enum.h
- // PK_FILTER_ENUM_SUPPORTED,
- // PK_FILTER_ENUM_NOT_SUPPORTED,
- }
-
- return FALSE;
-}
-
-/*
- * Emit signals for the packages, -but- if we have an installed package
- * we don't notify the client that the package is also available, since
- * PK doesn't handle re-installs (by some quirk).
- */
-void
-zypp_emit_filtered_packages_in_list (PkBackendJob *job, PkBitfield filters, const vector<sat::Solvable> &v)
-{
- typedef vector<sat::Solvable>::const_iterator sat_it_t;
-
- vector<sat::Solvable> installed;
-
- // always emit system installed packages first
- for (sat_it_t it = v.begin (); it != v.end (); ++it) {
- if (!it->isSystem() ||
- zypp_filter_solvable (filters, *it))
- continue;
-
- zypp_backend_package (job, PK_INFO_ENUM_INSTALLED, *it,
- make<ResObject>(*it)->summary().c_str());
- installed.push_back (*it);
- }
-
- // then available packages later
- for (sat_it_t it = v.begin (); it != v.end (); ++it) {
- gboolean match;
-
- if (it->isSystem() ||
- zypp_filter_solvable (filters, *it))
- continue;
-
- match = FALSE;
- for (sat_it_t i = installed.begin (); !match && i != installed.end (); i++) {
- match = it->sameNVRA (*i) &&
- !(!isKind<SrcPackage>(*it) ^
- !isKind<SrcPackage>(*i));
- }
- if (!match) {
- zypp_backend_package (job, PK_INFO_ENUM_AVAILABLE, *it,
- make<ResObject>(*it)->summary().c_str());
- }
- }
-}
-
-void
-zypp_backend_package (PkBackendJob *job, PkInfoEnum info,
- const sat::Solvable &pkg,
- const char *opt_summary)
-{
- gchar *id = zypp_build_package_id_from_resolvable (pkg);
- pk_backend_job_package (job, info, id, opt_summary);
- g_free (id);
-}
-
-/**
- * Returns a set of all packages the could be updated
- * (you're able to exclude a single (normally the 'patch' repo)
- */
-static void
-zypp_get_package_updates (string repo, set<PoolItem> &pks)
-{
- ResPool pool = ResPool::instance ();
-
- ResObject::Kind kind = ResTraits<Package>::kind;
- ResPool::byKind_iterator it = pool.byKindBegin (kind);
- ResPool::byKind_iterator e = pool.byKindEnd (kind);
-
- getZYpp()->resolver()->doUpdate();
- for (; it != e; ++it)
- if (it->status().isToBeInstalled()) {
- ui::Selectable::constPtr s =
- ui::Selectable::get((*it)->kind(), (*it)->name());
- if (s->hasInstalledObj())
- pks.insert(*it);
- }
-}
-
-/**
- * Returns a set of all patches the could be installed
- */
-static void
-zypp_get_patches (PkBackendJob *job, ZYpp::Ptr zypp, set<PoolItem> &patches)
-{
- _updating_self = FALSE;
-
- zypp->resolver ()->setIgnoreAlreadyRecommended (TRUE);
- zypp->resolver ()->resolvePool ();
-
- for (ResPoolProxy::const_iterator it = zypp->poolProxy ().byKindBegin<Patch>();
- it != zypp->poolProxy ().byKindEnd<Patch>(); it ++) {
- // check if the patch is needed and not set to taboo
- if((*it)->isNeeded() && !((*it)->candidateObj ().isUnwanted())) {
- Patch::constPtr patch = asKind<Patch>((*it)->candidateObj ().resolvable ());
- if (_updating_self) {
- if (patch->restartSuggested ())
- patches.insert ((*it)->candidateObj ());
- }
- else
- patches.insert ((*it)->candidateObj ());
-
- // check if the patch updates libzypp or packageKit and show only these
- if (!_updating_self && patch->restartSuggested ()) {
- _updating_self = TRUE;
- patches.clear ();
- patches.insert ((*it)->candidateObj ());
- }
- }
-
- }
-}
-
-void
-zypp_get_updates (PkBackendJob *job, ZYpp::Ptr zypp, set<PoolItem> &candidates)
-{
- typedef set<PoolItem>::iterator pi_it_t;
- zypp_get_patches (job, zypp, candidates);
-
- if (!_updating_self) {
- // exclude the patch-repository
- string patchRepo;
- if (!candidates.empty ()) {
- patchRepo = candidates.begin ()->resolvable ()->repoInfo ().alias ();
- }
-
- bool hidePackages = false;
- if (PathInfo("/etc/PackageKit/ZYpp.conf").isExist()) {
- parser::IniDict vendorConf(InputStream("/etc/PackageKit/ZYpp.conf"));
- if (vendorConf.hasSection("Updates")) {
- for ( parser::IniDict::entry_const_iterator eit = vendorConf.entriesBegin("Updates");
- eit != vendorConf.entriesEnd("Updates");
- ++eit )
- {
- if ((*eit).first == "HidePackages" &&
- str::strToTrue((*eit).second))
- hidePackages = true;
- }
- }
- }
-
- if (!hidePackages)
- {
- set<PoolItem> packages;
- zypp_get_package_updates(patchRepo, packages);
-
- pi_it_t cb = candidates.begin (), ce = candidates.end (), ci;
- for (ci = cb; ci != ce; ++ci) {
- if (!isKind<Patch>(ci->resolvable()))
- continue;
-
- Patch::constPtr patch = asKind<Patch>(ci->resolvable());
-
- // Remove contained packages from list of packages to add
- sat::SolvableSet::const_iterator pki;
- Patch::Contents content(patch->contents());
- for (pki = content.begin(); pki != content.end(); ++pki) {
-
- pi_it_t pb = packages.begin (), pe = packages.end (), pi;
- for (pi = pb; pi != pe; ++pi) {
- if (pi->satSolvable() == sat::Solvable::noSolvable)
- continue;
-
- if (pi->satSolvable().identical (*pki)) {
- packages.erase (pi);
- break;
- }
- }
- }
- }
-
- // merge into the list
- candidates.insert (packages.begin (), packages.end ());
- }
- }
-}
-
-void
-zypp_check_restart (PkRestartEnum *restart, Patch::constPtr patch)
-{
- if (patch == NULL || restart == NULL)
- return;
-
- // set the restart flag if a restart is needed
- if (*restart != PK_RESTART_ENUM_SYSTEM &&
- ( patch->reloginSuggested () ||
- patch->restartSuggested () ||
- patch->rebootSuggested ()) ) {
- if (patch->reloginSuggested () || patch->restartSuggested ())
- *restart = PK_RESTART_ENUM_SESSION;
- if (patch->rebootSuggested ())
- *restart = PK_RESTART_ENUM_SYSTEM;
- }
-}
-
-gboolean
-zypp_perform_execution (PkBackendJob *job, ZYpp::Ptr zypp, PerformType type, gboolean force, PkBitfield transaction_flags)
-{
- MIL << force << " " << pk_filter_bitfield_to_string(transaction_flags) << endl;
- gboolean ret = FALSE;
-
- PkBackend *backend = PK_BACKEND(pk_backend_job_get_backend(job));
-
- try {
- if (force)
- zypp->resolver ()->setForceResolve (force);
-
- // Gather up any dependencies
- pk_backend_job_set_status (job, PK_STATUS_ENUM_DEP_RESOLVE);
- zypp->resolver ()->setIgnoreAlreadyRecommended (TRUE);
- if (!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;
-
- 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 ())
- it->statusReset ();
- }
-
- pk_backend_job_error_code (job, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, emsg);
- g_free (emsg);
-
- goto exit;
- }
-
- switch (type) {
- case INSTALL:
- pk_backend_job_set_status (job, PK_STATUS_ENUM_INSTALL);
- break;
- case REMOVE:
- pk_backend_job_set_status (job, PK_STATUS_ENUM_REMOVE);
- break;
- case UPDATE:
- pk_backend_job_set_status (job, PK_STATUS_ENUM_UPDATE);
- break;
- }
-
- ResPool pool = ResPool::instance ();
- if (pk_bitfield_contain (transaction_flags, PK_TRANSACTION_FLAG_ENUM_SIMULATE)) {
- ret = TRUE;
-
- MIL << "simulating" << endl;
-
- for (ResPool::const_iterator it = pool.begin (); it != pool.end (); ++it) {
- if (type == REMOVE && !(*it)->isSystem ()) {
- it->statusReset ();
- continue;
- }
- // for updates we only care for updates
- if (type == UPDATE && it->status ().isToBeUninstalledDueToUpgrade ())
- continue;
-
- if (!zypp_backend_pool_item_notify (job, *it, TRUE))
- ret = FALSE;
- it->statusReset ();
- }
- goto exit;
- }
-
-
- // look for licenses to confirm
-
- for (ResPool::const_iterator it = pool.begin (); it != pool.end (); ++it) {
- if (it->status ().isToBeInstalled () && !(it->resolvable()->licenseToConfirm().empty ())) {
- gchar *eula_id = g_strdup ((*it)->name ().c_str ());
- gboolean has_eula = pk_backend_is_eula_valid (backend, eula_id);
- if (!has_eula) {
- gchar *package_id = zypp_build_package_id_from_resolvable (it->satSolvable ());
- pk_backend_job_eula_required (job,
- eula_id,
- package_id,
- (*it)->vendor ().c_str (),
- it->resolvable()->licenseToConfirm().c_str ());
- pk_backend_job_error_code (job, PK_ERROR_ENUM_NO_LICENSE_AGREEMENT, "You've to agree/decline a license");
- g_free (package_id);
- g_free (eula_id);
- goto exit;
- }
- g_free (eula_id);
- }
- }
-
- // Perform the installation
- gboolean only_download = pk_bitfield_contain (transaction_flags, PK_TRANSACTION_FLAG_ENUM_ONLY_DOWNLOAD);
-
- ZYppCommitPolicy policy;
- policy.restrictToMedia (0); // 0 == install all packages regardless to media
- if (only_download)
- policy.downloadMode(DownloadOnly);
- else
- policy.downloadMode (DownloadInHeaps);
-
- policy.syncPoolAfterCommit (true);
- if (!pk_bitfield_contain (transaction_flags, PK_TRANSACTION_FLAG_ENUM_ONLY_TRUSTED))
- policy.rpmNoSignature(true);
-
- ZYppCommitResult result = zypp->commit (policy);
-
- bool worked = result.allDone();
- if (only_download)
- worked = result.noError();
-
- if ( ! worked )
- {
- std::ostringstream todolist;
- char separator = '\0';
-
- // process all steps not DONE (ERROR and TODO)
- const sat::Transaction & trans( result.transaction() );
- for_( it, trans.actionBegin(~sat::Transaction::STEP_DONE), trans.actionEnd() )
- {
- if ( separator )
- todolist << separator << it->ident();
- else
- {
- todolist << it->ident();
- separator = '\n';
- }
- }
-
- pk_backend_job_error_code (job, PK_ERROR_ENUM_TRANSACTION_ERROR,
- "Transaction could not be completed.\n Theses packages could not be installed: %s",
- todolist.str().c_str());
-
- goto exit;
- }
-
- ret = TRUE;
- } catch (const repo::RepoNotFoundException &ex) {
- pk_backend_job_error_code (job, PK_ERROR_ENUM_REPO_NOT_FOUND, ex.asUserString().c_str() );
- } catch (const target::rpm::RpmException &ex) {
- pk_backend_job_error_code (job, PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED, ex.asUserString().c_str () );
- } catch (const Exception &ex) {
- pk_backend_job_error_code (job, PK_ERROR_ENUM_INTERNAL_ERROR, ex.asUserString().c_str() );
- }
-
- exit:
- /* reset the various options */
- try {
- zypp->resolver ()->setForceResolve (FALSE);
- } catch (const Exception &ex) { /* we tried */ }
-
- return ret;
-}
-
-GPtrArray *
-zypp_build_package_id_capabilities (Capabilities caps, gboolean terminate)
-{
- GPtrArray *package_ids = g_ptr_array_new();
-
- sat::WhatProvides provs (caps);
-
- for (sat::WhatProvides::const_iterator it = provs.begin (); it != provs.end (); ++it) {
- gchar *package_id = zypp_build_package_id_from_resolvable (*it);
- g_ptr_array_add(package_ids, package_id);
- }
- if (terminate)
- g_ptr_array_add(package_ids, NULL);
- return package_ids;
-}
-
-gboolean
-zypp_refresh_cache (PkBackendJob *job, ZYpp::Ptr zypp, gboolean force)
-{
- MIL << force << endl;
- // This call is needed as it calls initializeTarget which appears to properly setup the keyring
-
- if (zypp == NULL)
- return FALSE;
- filesystem::Pathname pathname("/");
- // This call is needed to refresh system rpmdb status while refresh cache
- zypp->finishTarget ();
- zypp->initializeTarget (pathname);
-
- pk_backend_job_set_status (job, PK_STATUS_ENUM_REFRESH_CACHE);
- pk_backend_job_set_percentage (job, 0);
-
- RepoManager manager;
- list <RepoInfo> repos;
- try
- {
- repos = list<RepoInfo>(manager.repoBegin(),manager.repoEnd());
- }
- catch ( const Exception &e)
- {
- // FIXME: make sure this dumps out the right sring.
- pk_backend_job_error_code (job, PK_ERROR_ENUM_REPO_NOT_FOUND, e.asUserString().c_str() );
- return FALSE;
- }
-
- int i = 1;
- int num_of_repos = repos.size ();
- gchar *repo_messages = NULL;
-
- for (list <RepoInfo>::iterator it = repos.begin(); it != repos.end(); ++it, i++) {
- RepoInfo repo (*it);
-
- if (!zypp_is_valid_repo (job, repo))
- return FALSE;
- if (pk_backend_job_get_is_error_set (job))
- break;
-
- // skip disabled repos
- if (repo.enabled () == false)
- continue;
-
- // do as zypper does
- if (!force && !repo.autorefresh())
- continue;
-
- // skip changeable meda (DVDs and CDs). Without doing this,
- // the disc would be required to be physically present.
- if (zypp_is_changeable_media (*repo.baseUrlsBegin ()) == true)
- continue;
-
- try {
- // Refreshing metadata
- g_free (_repoName);
- _repoName = g_strdup (repo.alias ().c_str ());
- zypp_refresh_meta_and_cache (manager, repo, force);
- } catch (const Exception &ex) {
- if (repo_messages == NULL) {
- repo_messages = g_strdup_printf ("%s: %s%s", repo.alias ().c_str (), ex.asUserString ().c_str (), "\n");
- } else {
- repo_messages = g_strdup_printf ("%s%s: %s%s", repo_messages, repo.alias ().c_str (), ex.asUserString ().c_str (), "\n");
- }
- if (repo_messages == NULL || !g_utf8_validate (repo_messages, -1, NULL))
- repo_messages = g_strdup ("A repository could not be refreshed");
- g_strdelimit (repo_messages, "\\\f\r\t", ' ');
- continue;
- }
-
- // Update the percentage completed
- pk_backend_job_set_percentage (job, i >= num_of_repos ? 100 : (100 * i) / num_of_repos);
- }
- if (repo_messages != NULL)
- pk_backend_job_message (job, PK_MESSAGE_ENUM_CONNECTION_REFUSED, repo_messages);
-
- g_free (repo_messages);
- return TRUE;
-}
-
-void
-zypp_backend_finished_error (PkBackendJob *job, PkErrorEnum err_code,
- const char *format, ...)
-{
- va_list args;
- gchar *buffer;
-
- /* sadly no _va variant for error code setting */
- va_start (args, format);
- buffer = g_strdup_vprintf (format, args);
- va_end (args);
-
- pk_backend_job_error_code (job, err_code, "%s", buffer);
-
- g_free (buffer);
-
- pk_backend_job_finished (job);
-}
-
-gboolean
-zypp_backend_pool_item_notify (PkBackendJob *job,
- const PoolItem &item,
- gboolean sanity_check)
-{
- PkInfoEnum status = PK_INFO_ENUM_UNKNOWN;
-
- if (item.status ().isToBeUninstalledDueToUpgrade ()) {
- MIL << "updating " << item << endl;
- status = PK_INFO_ENUM_UPDATING;
- } else if (item.status ().isToBeUninstalledDueToObsolete ()) {
- status = PK_INFO_ENUM_OBSOLETING;
- } else if (item.status ().isToBeInstalled ()) {
- MIL << "installing " << item << endl;
- status = PK_INFO_ENUM_INSTALLING;
- } else if (item.status ().isToBeUninstalled ()) {
- status = PK_INFO_ENUM_REMOVING;
-
- const string &name = item.satSolvable().name();
- if (name == "glibc" || name == "PackageKit" ||
- name == "rpm" || name == "libzypp") {
- pk_backend_job_error_code (job, PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE,
- "The package %s is essential to correct operation and cannot be removed using this tool.",
- name.c_str());
- return FALSE;
- }
- }
-
- // FIXME: do we need more heavy lifting here cf. zypper's
- // Summary.cc (readPool) to generate _DOWNGRADING types ?
- if (status != PK_INFO_ENUM_UNKNOWN) {
- const string &summary = item.resolvable ()->summary ();
- zypp_backend_package (job, status, item.resolvable()->satSolvable(), summary.c_str ());
- }
- return TRUE;
-}
-
-gchar *
-zypp_build_package_id_from_resolvable (const sat::Solvable &resolvable)
-{
- gchar *package_id;
- const char *arch;
-
- if (isKind<SrcPackage>(resolvable))
- arch = "source";
- else
- arch = resolvable.arch ().asString ().c_str ();
-
- string repo = resolvable.repository ().alias();
- if (resolvable.isSystem())
- repo = "installed";
- package_id = pk_package_id_build (
- resolvable.name ().c_str (),
- resolvable.edition ().asString ().c_str (),
- arch, repo.c_str ());
-
- return package_id;
-}
-
diff --git a/backends/zypp/zypp-utils.h b/backends/zypp/zypp-utils.h
deleted file mode 100644
index 797ac2e..0000000
--- a/backends/zypp/zypp-utils.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (c) 2007 Novell, Inc.
- * Copyright (c) 2007 Boyd Timothy <btimothy@gmail.com>
- * Copyright (c) 2007-2008 Stefan Haas <shaas@suse.de>
- * Copyright (c) 2007-2008 Scott Reeves <sreeves@novell.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef _ZYPP_UTILS_H_
-#define _ZYPP_UTILS_H_
-
-#undef ZYPP_BASE_LOGGER_LOGGROUP
-#define ZYPP_BASE_LOGGER_LOGGROUP "packagekit"
-
-#include <stdlib.h>
-#include <glib.h>
-#include <zypp/RepoManager.h>
-#include <zypp/media/MediaManager.h>
-#include <zypp/Resolvable.h>
-#include <zypp/ResPool.h>
-#include <zypp/PoolQuery.h>
-#include <zypp/ResFilters.h>
-#include <packagekit-glib2/pk-enum.h>
-
-#include <iterator>
-#include <list>
-#include <set>
-
-// some typedefs and functions to shorten Zypp names
-typedef zypp::ResPoolProxy ZyppPool;
-//inline ZyppPool zyppPool() { return zypp::getZYpp()->poolProxy(); }
-typedef zypp::ui::Selectable::Ptr ZyppSelectable;
-typedef zypp::ui::Selectable* ZyppSelectablePtr;
-typedef zypp::ResObject::constPtr ZyppObject;
-typedef zypp::Package::constPtr ZyppPackage;
-//typedef zypp::Patch::constPtr ZyppPatch;
-//typedef zypp::Pattern::constPtr ZyppPattern;
-//inline ZyppPackage tryCastToZyppPkg (ZyppObject obj)
-// { return zypp::dynamic_pointer_cast <const zypp::Package> (obj); }
-
-typedef enum {
- INSTALL,
- REMOVE,
- UPDATE
-} PerformType;
-
-/** Used to show/install only an update to ourself. This way if we find a critical bug
- * in the way we update packages we will install the fix before any other updates.
- */
-extern gboolean _updating_self;
-
-/** A string to store the last refreshed repo
- * this is needed for gpg-key handling stuff (UGLY HACK)
- * FIXME
- */
-extern gchar *_repoName;
-
-class ZyppJob {
- public:
- ZyppJob(PkBackendJob *job);
- ~ZyppJob();
- zypp::ZYpp::Ptr get_zypp();
-};
-
-/**
- * Enable and rotate logging
- */
-gboolean zypp_logging ();
-
-gboolean zypp_is_development_repo (zypp::RepoInfo repo);
-
-gboolean zypp_is_valid_repo (PkBackendJob *job, zypp::RepoInfo repo);
-/**
- * Build and return a ResPool that contains all local resolvables
- * and ones found in the enabled repositories.
- */
-zypp::ResPool zypp_build_pool (zypp::ZYpp::Ptr zypp, gboolean include_local);
-
-/**
-* check and warns the user that a repository may be outdated
-*/
-void warn_outdated_repos(PkBackendJob *job, const zypp::ResPool & pool);
-
-/**
- * Return the rpmHeader of a package
- */
-zypp::target::rpm::RpmHeader::constPtr zypp_get_rpmHeader (const std::string &name, zypp::Edition edition);
-
-/**
- * Return the PkEnumGroup of the given PoolItem.
- */
-PkGroupEnum get_enum_group (const std::string &group);
-
-/**
- * Returns a list of packages that match the specified package_name.
- */
-void zypp_get_packages_by_name (const gchar *package_name,
- const zypp::ResKind kind, std::vector<zypp::sat::Solvable> &result,
- gboolean include_local = TRUE);
-
-/**
- * Returns a list of packages that owns the specified file.
- */
-void zypp_get_packages_by_file (zypp::ZYpp::Ptr zypp, const gchar *search_file, std::vector<zypp::sat::Solvable> &result);
-
-/**
- * Returns the Resolvable for the specified package_id.
- */
-zypp::sat::Solvable zypp_get_package_by_id (const gchar *package_id);
-
-/**
- * Build a package_id from the specified resolvable. The returned
- * gchar * should be freed with g_free ().
- */
-gchar * zypp_build_package_id_from_resolvable (const zypp::sat::Solvable &resolvable);
-
-/**
- * Ask the User if it is OK to import an GPG-Key for a repo
- */
-gboolean zypp_signature_required (PkBackendJob *job, const zypp::PublicKey &key);
-
-/**
- * Ask the User if it is OK to refresh the Repo while we don't know the key
- */
-gboolean zypp_signature_required (PkBackendJob *job, const std::string &file);
-
-/**
- * Ask the User if it is OK to refresh the Repo while we don't know the key, only its id which was never seen before
- */
-gboolean zypp_signature_required (PkBackendJob *job, const std::string &file, const std::string &id);
-
-/**
- * Find best (according to edition) uninstalled item with the same kind/name/arch as item.
- */
-zypp::PoolItem zypp_find_arch_update_item (const zypp::ResPool & pool, zypp::PoolItem item);
-
-/**
- * Return the best, most friendly selection of update patches and packages that
- * we can find. Also manages _updating_self to prioritise critical infrastructure
- * updates.
- */
-void zypp_get_updates (PkBackendJob *job, zypp::ZYpp::Ptr zypp, std::set<zypp::PoolItem> &);
-
-/**
- * Sets the restart flag of a patch
- */
-void zypp_check_restart (PkRestartEnum *restart, zypp::Patch::constPtr patch);
-
-/**
- * simulate, or perform changes in pool to the system
- */
-gboolean zypp_perform_execution (PkBackendJob *job, zypp::ZYpp::Ptr zypp, PerformType type, gboolean force, PkBitfield transaction_flags);
-
-/**
- * should we omit a solvable from a result because of filtering ?
- */
-gboolean zypp_filter_solvable (PkBitfield filters, const zypp::sat::Solvable &item);
-
-/**
- * apply filters to a list.
- */
-void zypp_emit_filtered_packages_in_list (PkBackendJob *job, PkBitfield _filters, const std::vector<zypp::sat::Solvable> &list);
-
-/**
- * build array of package_id's seperated by blanks out of the capabilities of a solvable
- */
-GPtrArray * zypp_build_package_id_capabilities (zypp::Capabilities caps, gboolean terminate = TRUE);
-
-/**
- * refresh the enabled repositories
- */
-gboolean zypp_refresh_cache (PkBackendJob *job, zypp::ZYpp::Ptr zypp, gboolean force);
-
-/**
- * helper to simplify returning errors
- */
-void zypp_backend_finished_error (PkBackendJob *job, PkErrorEnum err_code,
- const char *format, ...);
-
-/**
- * helper to emit pk package signals for a backend for a zypp solvable
- */
-void zypp_backend_package (PkBackendJob *job, PkInfoEnum info,
- const zypp::sat::Solvable &pkg,
- const char *opt_summary);
-
-/**
- * helper to emit pk package status signals based on a ResPool object
- */
-gboolean zypp_backend_pool_item_notify (PkBackendJob *job,
- const zypp::PoolItem &item,
- gboolean sanity_check = FALSE);
-
-/**
- * helper to refresh a repo's metadata and cache, catching signature
- * exceptions in a safe way.
- */
-gboolean zypp_refresh_meta_and_cache (zypp::RepoManager &manager, zypp::RepoInfo &repo, bool force = false);
-
-#endif // _ZYPP_UTILS_H_
-
--
1.8.1.1