300 lines
8.3 KiB
C++
300 lines
8.3 KiB
C++
#ifndef _ZYPP_EVENTS_H_
|
|
#define _ZYPP_EVENTS_H_
|
|
|
|
#include <stdio.h>
|
|
#include <glib.h>
|
|
#include <pk-backend.h>
|
|
#include <zypp/ZYppCallbacks.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
|
|
{
|
|
|
|
struct ZyppBackendReceiver
|
|
{
|
|
PkBackend *_backend;
|
|
gchar *_package_id;
|
|
guint _sub_percentage;
|
|
|
|
virtual void initWithBackend (PkBackend *backend)
|
|
{
|
|
_backend = backend;
|
|
_package_id = NULL;
|
|
_sub_percentage = 0;
|
|
}
|
|
|
|
virtual void clear_package_id ()
|
|
{
|
|
if (_package_id != NULL) {
|
|
g_free (_package_id);
|
|
_package_id = NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build a package_id from the specified zypp::Url. The returned
|
|
* gchar * should be freed with g_free (). Returns NULL if the
|
|
* URL does not contain information about an RPM.
|
|
*
|
|
* Example:
|
|
* basename: lynx-2.8.6-63.i586.rpm
|
|
* result: lynx;2.8.6-63;i586;opensuse
|
|
*/
|
|
gchar *
|
|
build_package_id_from_url (const zypp::Url *url)
|
|
{
|
|
gchar *package_id;
|
|
gchar *basename;
|
|
gchar *tmp;
|
|
|
|
gchar *arch;
|
|
gchar *edition;
|
|
gchar *name;
|
|
gboolean first_dash_found;
|
|
|
|
basename = g_strdup (zypp::Pathname (url->getPathName ()).basename ().c_str());
|
|
|
|
tmp = g_strrstr (basename, ".rpm");
|
|
|
|
if (tmp == NULL) {
|
|
g_free (basename);
|
|
return NULL;
|
|
}
|
|
|
|
// Parse the architecture
|
|
tmp [0] = '\0'; // null-terminate the arch section
|
|
for (tmp--; tmp != basename && tmp [0] != '.'; tmp--) {}
|
|
arch = tmp + 1;
|
|
|
|
// Parse the edition
|
|
tmp [0] = '\0'; // null-terminate the edition (version)
|
|
first_dash_found = FALSE;
|
|
for (tmp--; tmp != basename; tmp--) {
|
|
if (tmp [0] == '-') {
|
|
if (first_dash_found == FALSE) {
|
|
first_dash_found = TRUE;
|
|
continue;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
edition = tmp + 1;
|
|
|
|
// Parse the name
|
|
tmp [0] = '\0'; // null-terminate the name
|
|
name = basename;
|
|
|
|
package_id = pk_package_id_build (name, edition, arch, "opensuse");
|
|
g_free (basename);
|
|
|
|
return package_id;
|
|
}
|
|
|
|
inline void
|
|
update_sub_percentage (guint percentage)
|
|
{
|
|
// TODO: Figure out this weird bug that libzypp emits a 100
|
|
// at the beginning of installing a package.
|
|
if (_sub_percentage == 0 && percentage == 100)
|
|
return; // can't jump from 0 -> 100 instantly!
|
|
|
|
// 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).
|
|
|
|
// Drop off the least significant digit
|
|
// TODO: Figure out a faster way to drop the least significant digit
|
|
percentage = (percentage / 10) * 10;
|
|
|
|
if (percentage <= _sub_percentage)
|
|
return;
|
|
|
|
_sub_percentage = percentage;
|
|
//PercentageData *pd = (PercentageData *)malloc (sizeof (PercentageData));
|
|
//pd->backend = _backend;
|
|
//pd->percentage = _sub_percentage;
|
|
//g_idle_add (emit_sub_percentage, pd);
|
|
pk_backend_set_sub_percentage (_backend, _sub_percentage);
|
|
}
|
|
|
|
void
|
|
reset_sub_percentage ()
|
|
{
|
|
_sub_percentage = 0;
|
|
pk_backend_set_sub_percentage (_backend, _sub_percentage);
|
|
}
|
|
};
|
|
|
|
struct InstallResolvableReportReceiver : public zypp::callback::ReceiveReport<zypp::target::rpm::InstallResolvableReport>, ZyppBackendReceiver
|
|
{
|
|
zypp::Resolvable::constPtr _resolvable;
|
|
|
|
virtual void start (zypp::Resolvable::constPtr resolvable)
|
|
{
|
|
clear_package_id ();
|
|
_package_id = zypp_build_package_id_from_resolvable (resolvable);
|
|
//fprintf (stderr, "\n\n----> InstallResolvableReportReceiver::start(): %s\n\n", _package_id == NULL ? "unknown" : _package_id);
|
|
if (_package_id != NULL) {
|
|
pk_backend_set_status (_backend, PK_STATUS_ENUM_INSTALL);
|
|
pk_backend_package (_backend, PK_INFO_ENUM_INSTALLING, _package_id, "TODO: Put the package summary here if possible");
|
|
reset_sub_percentage ();
|
|
}
|
|
}
|
|
|
|
virtual bool progress (int value, zypp::Resolvable::constPtr resolvable)
|
|
{
|
|
//fprintf (stderr, "\n\n----> InstallResolvableReportReceiver::progress(), %s:%d\n\n", _package_id == NULL ? "unknown" : _package_id, value);
|
|
if (_package_id != NULL)
|
|
update_sub_percentage (value);
|
|
return true;
|
|
}
|
|
|
|
virtual Action problem (zypp::Resolvable::constPtr resolvable, Error error, const std::string &description, RpmLevel level)
|
|
{
|
|
//fprintf (stderr, "\n\n----> InstallResolvableReportReceiver::problem()\n\n");
|
|
return ABORT;
|
|
}
|
|
|
|
virtual void finish (zypp::Resolvable::constPtr resolvable, Error error, const std::string &reason, RpmLevel level)
|
|
{
|
|
//fprintf (stderr, "\n\n----> InstallResolvableReportReceiver::finish(): %s\n\n", _package_id == NULL ? "unknown" : _package_id);
|
|
if (_package_id != NULL) {
|
|
pk_backend_package (_backend, PK_INFO_ENUM_INSTALLED, _package_id, "TODO: Put the package summary here if possible");
|
|
clear_package_id ();
|
|
}
|
|
}
|
|
};
|
|
|
|
struct RepoProgressReportReceiver : public zypp::callback::ReceiveReport<zypp::ProgressReport>, ZyppBackendReceiver
|
|
{
|
|
virtual void start (const zypp::ProgressData &data)
|
|
{
|
|
//fprintf (stderr, "\n\n----> RepoProgressReportReceiver::start()\n\n");
|
|
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)
|
|
{
|
|
//fprintf (stderr, "\n\n----> RepoReportReceiver::start()\n");
|
|
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 (const zypp::ProgressData &data)
|
|
{
|
|
//fprintf (stderr, "\n\n----> RepoReportReceiver::finish()\n");
|
|
}
|
|
};
|
|
|
|
struct DownloadProgressReportReceiver : public zypp::callback::ReceiveReport<zypp::media::DownloadProgressReport>, ZyppBackendReceiver
|
|
{
|
|
virtual void start (const zypp::Url &file, zypp::Pathname localfile)
|
|
{
|
|
clear_package_id ();
|
|
_package_id = build_package_id_from_url (&file);
|
|
|
|
//fprintf (stderr, "\n\n----> DownloadProgressReportReceiver::start(): %s\n", _package_id == NULL ? "unknown" : _package_id);
|
|
if (_package_id != NULL) {
|
|
pk_backend_set_status (_backend, PK_STATUS_ENUM_DOWNLOAD);
|
|
pk_backend_package (_backend, PK_INFO_ENUM_DOWNLOADING, _package_id, "TODO: Put the package summary here if possible");
|
|
reset_sub_percentage ();
|
|
}
|
|
}
|
|
|
|
virtual bool progress (int value, const zypp::Url &file)
|
|
{
|
|
//fprintf (stderr, "\n\n----> DownloadProgressReportReceiver::progress(), %s:%d\n\n", _package_id == NULL ? "unknown" : _package_id, value);
|
|
if (_package_id != NULL)
|
|
update_sub_percentage (value);
|
|
return true;
|
|
}
|
|
|
|
virtual void finish (const zypp::Url & file, Error error, const std::string &konreason)
|
|
{
|
|
//fprintf (stderr, "\n\n----> DownloadProgressReportReceiver::finish(): %s\n", _package_id == NULL ? "unknown" : _package_id);
|
|
clear_package_id ();
|
|
}
|
|
};
|
|
|
|
}; // namespace ZyppBackend
|
|
|
|
class EventDirector
|
|
{
|
|
private:
|
|
EventDirector () {}
|
|
|
|
ZyppBackend::RepoReportReceiver _repoReport;
|
|
ZyppBackend::RepoProgressReportReceiver _repoProgressReport;
|
|
ZyppBackend::InstallResolvableReportReceiver _installResolvableReport;
|
|
ZyppBackend::DownloadProgressReportReceiver _downloadProgressReport;
|
|
|
|
public:
|
|
EventDirector (PkBackend *backend)
|
|
{
|
|
_repoReport.initWithBackend (backend);
|
|
_repoReport.connect ();
|
|
|
|
_repoProgressReport.initWithBackend (backend);
|
|
_repoProgressReport.connect ();
|
|
|
|
_installResolvableReport.initWithBackend (backend);
|
|
_installResolvableReport.connect ();
|
|
|
|
_downloadProgressReport.initWithBackend (backend);
|
|
_downloadProgressReport.connect ();
|
|
}
|
|
|
|
~EventDirector ()
|
|
{
|
|
_repoReport.disconnect ();
|
|
_repoProgressReport.disconnect ();
|
|
_installResolvableReport.disconnect ();
|
|
_downloadProgressReport.disconnect ();
|
|
}
|
|
};
|
|
|
|
|
|
#endif // _ZYPP_EVENTS_H_
|
|
|