diff -Naur PackageKit_upstream/backends/cards/job.cxx PackageKit/backends/cards/job.cxx --- PackageKit_upstream/backends/cards/job.cxx 1970-01-01 01:00:00.000000000 +0100 +++ PackageKit/backends/cards/job.cxx 2026-06-03 12:35:10.398875583 +0200 @@ -0,0 +1,261 @@ +#include "job.h" + +#include +#include +#include +#include +#include + +Job::Job(PkBackendJob *job) : + m_cache(nullptr), + m_job(job), + m_cancel(false) +{ +} +Job::~Job() +{ + delete m_cache; + for (auto pkg : m_packagesSet) { + if (pkg) + delete pkg; + } +} +bool Job::init() +{ + m_cache = new cards::pkgrepo("/etc/cards.conf"); + m_mapPackages = m_cache->getListOfPackages(); + + if (m_mapPackages.size() > 0) + return true; + return false; +} +void Job::cancel() +{ + if (!m_cancel) { + m_cancel = true; + pk_backend_job_set_status(m_job, PK_STATUS_ENUM_CANCEL); + } + + if (m_child_pid > 0) { + kill(m_child_pid, SIGTERM); + } +} + +bool Job::cancelled() const +{ + return m_cancel; +} + +PkBackendJob *Job::pkJob() const +{ + return m_job; +} +PkGroupEnum +Job::group_to_enum (const std::string& p) +{ + if (p.compare("doc")) + return PK_GROUP_ENUM_DOCUMENTATION; + else if ( p.compare("fr") || + p.compare("de") || + p.compare("es") || + p.compare("it") || + p.compare("pt") || + p.compare("nl") ) // TODO find another solution not completed ATM + return PK_GROUP_ENUM_LOCALIZATION; + else if (p.compare("devel")) + return PK_GROUP_ENUM_PROGRAMMING; + else if (p.compare("kde6")) + return PK_GROUP_ENUM_DESKTOP_KDE; + else if (p.compare("xfce4") || + p.compare("xfce4-extra")) + return PK_GROUP_ENUM_DESKTOP_XFCE; + else if (p.compare("gnome-base") || + p.compare("gnome") || + p.compare("gnome-extra")) + return PK_GROUP_ENUM_DESKTOP_GNOME; + else if (p.compare("service")) + return PK_GROUP_ENUM_SERVERS; + else if (p.compare("base")) + return PK_GROUP_ENUM_SYSTEM; + else + return PK_GROUP_ENUM_DESKTOP_OTHER; +} + +void Job::resolvePackages() +{ + g_debug("resolvePackges Started"); + + pk_backend_job_set_status (m_job, PK_STATUS_ENUM_QUERY); + + for (auto p : m_mapPackages) { + cards::cache* pkg = new cards::cache; + pkg->name(p.first); + pkg->description(p.second.description()); + pkg->arch(p.second.arch()); + pkg->version(p.second.version()); + pkg->collection(p.second.collection()); + if (p.second.group().empty()) { + if ( ! p.second.sets().empty()) { + for (auto s : p.second.sets()) { + pkg->group(s); + break; + } + } else + pkg->group(p.second.collection()); + } else + pkg->group(p.second.group()); + pkg->license("GPL2"); + if ( ! p.second.license().empty()) + pkg->license(p.second.license()); + pkg->url(p.second.url()); + pkg->space(p.second.space()); + m_packagesSet.insert(pkg); + + } +} +void Job::resolvePackageIds(gchar **package_ids) +{ + g_debug("resolvePackgesIds started"); + + pk_backend_job_set_status (m_job, PK_STATUS_ENUM_QUERY); + + if (package_ids == NULL) + return; + + + for (uint i = 0; i < g_strv_length(package_ids); ++i) { + if (m_cancel) + break; + std::string pi; + if (pk_package_id_check(package_ids[i])) { + g_auto(GStrv) parts = pk_package_id_split(package_ids[i]); + pi = parts[PK_PACKAGE_ID_NAME]; + } else { + pi = package_ids[i]; + } + g_debug(package_ids[i]); + for (auto p : m_mapPackages) { + + cards::cache* pkg = new cards::cache; + + std::string::size_type pos; + pos = convertToLowerCase(p.second.collection()).find(convertToLowerCase(pi)); + if (pos == std::string::npos) + pos = convertToLowerCase(p.first).find(convertToLowerCase(pi)); + if (pos == std::string::npos) + pos = convertToLowerCase(p.second.description()).find(convertToLowerCase(pi)); + if (pos == std::string::npos) + pos = convertToLowerCase(p.second.version()).find(convertToLowerCase(pi)); + if (pos != std::string::npos){ + pkg->name(p.first); + pkg->description(p.second.description()); + pkg->arch(p.second.arch()); + pkg->version(p.second.version()); + pkg->collection(p.second.collection()); + if (p.second.group().empty()) { + if ( ! p.second.sets().empty()) { + for (auto s : p.second.sets()) { + pkg->group(s); + break; + } + } else + pkg->group(p.second.collection()); + } else + pkg->group(p.second.group()); + pkg->license("GPL2"); + if (!p.second.license().empty()) + pkg->license(p.second.license()); + pkg->url(p.second.url()); + pkg->space(p.second.space()); + pkg->size(p.second.size()); + m_packagesSet.insert(pkg); + } + } + } +} +void Job::refreshCache() +{ + pk_backend_job_set_status(m_job, PK_STATUS_ENUM_REFRESH_CACHE); +} +void Job::emitPackageFiles(const gchar *pi) +{ + using namespace std; + GPtrArray *files; + string line; + + g_auto(GStrv) parts = pk_package_id_split(pi); + string fName; + fName = "/var/lib/pkg/DB/" + string(parts[PK_PACKAGE_ID_NAME]) + "/files"; + + if (checkFileExist(fName)) { + ifstream in(fName.c_str()); + if (!in != 0) { + return; + } + + files = g_ptr_array_new_with_free_func(g_free); + while (in.eof() == false) { + getline(in, line); + if (!line.empty()) { + g_ptr_array_add(files, g_strdup(line.c_str())); + } + } + + if (files->len) { + g_ptr_array_add(files, NULL); + pk_backend_job_files(m_job, pi, (gchar **) files->pdata); + } + g_ptr_array_unref(files); + } +} +void Job::emitPackages(PkBitfield filters, PkInfoEnum state) +{ + g_debug("emitPackages started"); + pkgdbh dbh; + dbh.buildDatabase(false); + + for (auto p : m_packagesSet) { + if(m_cancel) + break; + + std::string c = p->collection(); + + if (state == PK_INFO_ENUM_UNKNOWN) { + state = PK_INFO_ENUM_AVAILABLE; + if (dbh.checkPackageNameExist(p->name())) { + state = PK_INFO_ENUM_INSTALLED; + } + } + if (dbh.checkPackageNameExist(p->name())) + c = "installed"; + + std::string pi = p->name() + ";" + p->version() + + ";" + p->arch() + ";" + + p->description().c_str(); + pk_backend_job_package(m_job, state, pi.c_str(), p->description().c_str()); + } +} +void Job::emitDetails() +{ + + g_debug("emitDetails started"); + + for (auto p : m_packagesSet) { + if(m_cancel) + break; + + std::string pi = p->name() + ";" + + p->version() + ";" + p->arch() + + ";" + p->collection(); + + pk_backend_job_details (m_job, pi.c_str(), + p->description().c_str(), + p->license().c_str(), + group_to_enum(p->group()), + "", + p->url().c_str(), + p->space(), + p->size()); + } +} +// vim:set ts=2 : diff -Naur PackageKit_upstream/backends/cards/job.h PackageKit/backends/cards/job.h --- PackageKit_upstream/backends/cards/job.h 1970-01-01 01:00:00.000000000 +0100 +++ PackageKit/backends/cards/job.h 2026-06-03 12:35:42.097972783 +0200 @@ -0,0 +1,106 @@ +/* job.h + * + * Copyright (c) 2023 Thierry Nuttens + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#pragma once + +#include + +#include + +class Job +{ + cards::pkgrepo *m_cache; + cards::repo_t m_mapPackages; + std::set m_packagesSet; + PkBackendJob *m_job; + bool m_cancel; + pid_t m_child_pid; + +public: + Job(PkBackendJob *job); + ~Job(); + + bool init(); + void cancel(); + bool cancelled() const; + + /** + * Returns the PkBitfield for the specified Package. + */ + PkGroupEnum + group_to_enum (const std::string& p); + /** + * Returns the PackageKit backend job associated with this CARDS job. + */ + PkBackendJob *pkJob() const; + + /** + * Get the list of packages + * generate m_packageSet, if the list is empty no package was found + */ + void resolvePackages(); + + /** + * Tries to find a list of packages mathing the package ids + * generate m_packagesSet, if the list is empty no package was found + */ + void resolvePackageIds(gchar **package_ids); + + /** + * Return a package_id + * + */ + gchar* matchPackage(const std::string &package); + + /** + * Check if a given package matches the filters + * @return true if it passed the filters + */ + bool matchPackage(const std::string &PackageName, PkBitfield filters); + + /** + * Refreshes the sources of packages + */ + void refreshCache(); + + /** + * Emits the files of a package + */ + void emitPackageFiles(const gchar *pi); + + /** + * Emits the files of a package + */ + void emitPackageFilesLocal(const gchar *pi); + + + /** + * Emit m_packageSet that matches the given filters + */ + void emitPackages(PkBitfield filters = PK_FILTER_ENUM_NONE, + PkInfoEnum state = PK_INFO_ENUM_UNKNOWN); + + + /** + * Emit details + */ + void emitDetails(); +}; +// vim:set ts=2 : diff -Naur PackageKit_upstream/backends/cards/meson.build PackageKit/backends/cards/meson.build --- PackageKit_upstream/backends/cards/meson.build 1970-01-01 01:00:00.000000000 +0100 +++ PackageKit/backends/cards/meson.build 2026-05-22 15:39:46.648240952 +0200 @@ -0,0 +1,29 @@ +add_languages('cpp') + +cpp_compiler = meson.get_compiler('cpp') + +archive_dep = meson.get_compiler('c').find_library('archive') +curl_dep = meson.get_compiler('c').find_library('curl') +cards_dep = meson.get_compiler('c').find_library('cards') + +shared_module( + 'pk_backend_cards', + 'pk-backend-cards.cxx', + 'job.cxx', + 'job.h', + include_directories: packagekit_src_include, + dependencies: [ + packagekit_glib2_dep, + archive_dep, + curl_dep, + cards_dep, + gmodule_dep, + ], + cpp_args: [ + '-DPK_COMPILATION', + '-DG_LOG_DOMAIN="PackageKit-Cards"', + ], + override_options: ['c_std=c11','cpp_std=c++17'], + install: true, + install_dir: pk_plugin_dir, +) diff -Naur PackageKit_upstream/backends/cards/pk-backend-cards.cxx PackageKit/backends/cards/pk-backend-cards.cxx --- PackageKit_upstream/backends/cards/pk-backend-cards.cxx 1970-01-01 01:00:00.000000000 +0100 +++ PackageKit/backends/cards/pk-backend-cards.cxx 2026-06-03 12:36:05.289972695 +0200 @@ -0,0 +1,368 @@ +/* pk-backend-cards.cpp + * + * Copyright (C) 2007-2014 Richard Hughes + * Copyright (C) 2023 Thierry Nuttens + * + * 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 + +#include +#include + +#include + +#include "job.h" + +const gchar * pk_backend_get_description (PkBackend *backend) +{ + return "Cards backend"; +} + +const gchar * pk_backend_get_author (PkBackend *backend) +{ + return "Thierry Nuttens "; +} + +gboolean +pk_backend_supports_parallelization (PkBackend *backend) +{ + return FALSE; +} + +void +pk_backend_initialize (GKeyFile *conf, PkBackend *backend) +{ + pk_debug_add_log_domain (G_LOG_DOMAIN); + pk_debug_add_log_domain ("CARDS"); +} + +void +pk_backend_destroy (PkBackend *backend) +{ + g_debug("Cards backend being destroyed"); +} + +PkBitfield +pk_backend_get_groups (PkBackend *backend) +{ + return pk_bitfield_from_enums (PK_GROUP_ENUM_DOCUMENTATION, + PK_GROUP_ENUM_LOCALIZATION, + PK_GROUP_ENUM_SERVERS, + PK_GROUP_ENUM_PROGRAMMING, + PK_GROUP_ENUM_SYSTEM, + PK_GROUP_ENUM_DESKTOP_KDE, + PK_GROUP_ENUM_DESKTOP_XFCE, + PK_GROUP_ENUM_DESKTOP_GNOME, + PK_GROUP_ENUM_DESKTOP_OTHER, + -1); +} + +PkBitfield +pk_backend_get_filters (PkBackend *backend) +{ + return pk_bitfield_from_enums (PK_FILTER_ENUM_BASENAME, + PK_FILTER_ENUM_GUI, + PK_FILTER_ENUM_APPLICATION, + PK_FILTER_ENUM_INSTALLED, + PK_FILTER_ENUM_NOT_INSTALLED, + PK_FILTER_ENUM_DEVELOPMENT, + -1); +} + +gchar ** pk_backend_get_mime_types (PkBackend *backend) +{ + const gchar *mime_types[] = { + "application/x-xz-compressed-tar", + NULL }; + return g_strdupv ((gchar **) mime_types); +} + +void +pk_backend_start_job (PkBackend *backend, PkBackendJob *job) +{ + + /* create private state for this job */ + auto cards = new Job(job); + + /* you can use pk_backend_job_error_code() here too */ + pk_backend_job_set_user_data (job, cards); +} + +void +pk_backend_stop_job (PkBackend *backend, PkBackendJob *job) +{ + auto cards = static_cast(pk_backend_job_get_user_data (job)); + + if (cards) + delete cards; + + pk_backend_job_set_user_data (job, NULL); +} + +void +pk_backend_cancel (PkBackend *backend, PkBackendJob *job) +{ + auto cards = static_cast(pk_backend_job_get_user_data(job)); + if (cards) { + /* try to cancel the thread */ + g_debug ("cancelling transaction"); + cards->cancel(); + } +} +static void +backend_refresh_cache_thread (PkBackendJob *job, GVariant *params, gpointer user_data) +{ + g_debug("backend_refresh_cache_tread started"); + pk_backend_job_set_status(job, PK_STATUS_ENUM_REFRESH_CACHE); + pk_backend_job_set_percentage (job, 0); + cards::sync sync("/etc/cards.conf",false); + sync.run(); + pk_backend_job_set_percentage (job, 100); + pk_backend_job_finished (job); +} +void +pk_backend_refresh_cache (PkBackend *backend, PkBackendJob *job, gboolean force) +{ + pk_backend_job_thread_create (job, backend_refresh_cache_thread, NULL, NULL); +} +static void +backend_get_updates_thread (PkBackendJob *job, GVariant *params, gpointer user_data) +{ + g_debug("backend_get_updates_tread started"); + pk_backend_job_set_status (job, PK_STATUS_ENUM_QUERY); + pk_backend_job_set_percentage (job, 0); + cards::sync sync("/etc/cards.conf",false); + sync.run(); + pk_backend_job_set_percentage (job, 100); + pk_backend_job_finished (job); +} +void +pk_backend_get_updates (PkBackend *backend, PkBackendJob *job, PkBitfield filters) +{ + pk_backend_job_thread_create (job, backend_get_updates_thread, NULL, NULL); +} + +static void +backend_get_files_thread (PkBackendJob *job, GVariant *params, gpointer user_data) +{ + gchar **package_ids; // List of packages + gchar *pi; // Package installed + + g_variant_get(params, "(^a&s)", + &package_ids); + + auto cards = static_cast(pk_backend_job_get_user_data(job)); + if (!cards->init()) { + g_debug("Failed to create cards cache"); + return; + } + pk_backend_job_set_status(job, PK_STATUS_ENUM_QUERY); + for (uint i = 0; i < g_strv_length(package_ids); ++i) { + pi = package_ids[i]; + cards->emitPackageFiles(pi); + } + pk_backend_job_finished (job); +} + +void +pk_backend_get_files (PkBackend *backend, PkBackendJob *job, gchar **package_ids) +{ + pk_backend_job_thread_create(job, backend_get_files_thread, NULL, NULL); +} +void +pk_backend_resolve_thread (PkBackendJob *job, GVariant *params, gpointer user_data) +{ + g_debug("pk_backend_resolve_tread started"); + + gchar **search; + PkBitfield filters; + + g_variant_get(params, "(t^a&s)", + &filters, + &search); + pk_backend_job_set_allow_cancel(job, true); + + auto cards = static_cast(pk_backend_job_get_user_data(job)); + if (!cards->init()) { + g_debug("Failed to initialize CARDS job"); + pk_backend_job_finished (job); + return; + } + cards->resolvePackageIds(search); + + cards->emitPackages(filters,PK_INFO_ENUM_UNKNOWN); + pk_backend_job_finished (job); +} +void +pk_backend_resolve (PkBackend *backend, PkBackendJob *job, PkBitfield filters, gchar **package_ids) +{ + pk_backend_job_thread_create(job, pk_backend_resolve_thread, NULL, NULL); +} + +static void +backend_get_packages_thread (PkBackendJob *job, GVariant *params, gpointer user_data) +{ + PkBitfield filters; + g_variant_get(params, "(t)", &filters); + + auto cards = static_cast(pk_backend_job_get_user_data(job)); + if (!cards->init()) { + g_debug("Failed to create cards cache"); + pk_backend_job_finished (job); + return; + } + cards->resolvePackages(); + cards->emitPackages(filters,PK_INFO_ENUM_UNKNOWN); + pk_backend_job_finished (job); +} + +void pk_backend_get_packages(PkBackend *backend, PkBackendJob *job, PkBitfield filters) +{ + pk_backend_job_thread_create(job, backend_get_packages_thread, NULL, NULL); +} + +void +pk_backend_install_packages (PkBackend *backend, PkBackendJob *job, + PkBitfield transaction_flags, gchar **package_ids) +{ + pk_backend_job_finished (job); +} + +void +pk_backend_remove_packages (PkBackend *backend, PkBackendJob *job, + PkBitfield transaction_flags, gchar **package_ids, + gboolean allow_deps, gboolean autoremove) +{ + pk_backend_job_finished(job); +} +PkBitfield +pk_backend_get_roles (PkBackend *backend) +{ + PkBitfield roles; + roles = pk_bitfield_from_enums( + PK_ROLE_ENUM_CANCEL, + PK_ROLE_ENUM_GET_FILES, + PK_ROLE_ENUM_GET_PACKAGES, + PK_ROLE_ENUM_GET_REPO_LIST, + PK_ROLE_ENUM_GET_DETAILS, + PK_ROLE_ENUM_GET_DETAILS_LOCAL, + PK_ROLE_ENUM_RESOLVE, + PK_ROLE_ENUM_REFRESH_CACHE, + PK_ROLE_ENUM_GET_UPDATES, + PK_ROLE_ENUM_SEARCH_NAME, + PK_ROLE_ENUM_SEARCH_DETAILS, + PK_ROLE_ENUM_INSTALL_PACKAGES, + PK_ROLE_ENUM_REMOVE_PACKAGES, + -1); + + return roles; +} +void +pk_backend_get_details_thread (PkBackendJob *job, GVariant *params, gpointer user_data) +{ + g_debug("pk_backend_get_details_thread started"); + + gchar **search = nullptr; + + g_variant_get(params, "(^a&s)", &search); + + auto cards = static_cast(pk_backend_job_get_user_data(job)); + if (!cards->init()) { + g_debug("Failed to create cards cache"); + pk_backend_job_finished (job); + return; + } + + cards->resolvePackageIds(search); + cards->emitDetails(); + pk_backend_job_finished (job); +} +void +pk_backend_get_details (PkBackend *backend, PkBackendJob *job, gchar **package_ids) +{ + pk_backend_job_thread_create(job, pk_backend_get_details_thread, NULL, NULL); +} +void +pk_backend_get_repo_list (PkBackend *backend, PkBackendJob *job, PkBitfield filters) +{ + pk_backend_job_set_status (job, PK_STATUS_ENUM_QUERY); + + cards::conf conf("/etc/cards.conf"); + std::string url = "https://downloads.nutyx.org"; + std::string depot; + std::string collection; + for (auto i : conf.dirUrl()) { + if ( i.url != "" ) + url = i.url; + + depot = url + "/" + conf.arch() + "/" + conf.version() + "/" + i.collection; + collection = i.collection; + pk_backend_job_repo_detail (job, depot.c_str(), + collection.c_str(), + true); + } + pk_backend_job_finished (job); +} + +static void +backend_search_names_thread (PkBackendJob *job, GVariant *params, gpointer user_data) +{ + PkBitfield filters; + gchar **values; + g_variant_get(params, "(t^a&s)", &filters, &values); + + pk_backend_job_set_status(job, PK_STATUS_ENUM_QUERY); + + auto cards = static_cast(pk_backend_job_get_user_data(job)); + if (!cards->init()) { + g_debug("Failed to initialize CARDS job"); + pk_backend_job_finished(job); + return; + } + + cards->resolvePackageIds(values); + cards->emitPackages(filters, PK_INFO_ENUM_UNKNOWN); + + pk_backend_job_finished(job); +} +void pk_backend_search_details (PkBackend *backend, PkBackendJob *job, PkBitfield filters, gchar **values) +{ + pk_backend_job_thread_create(job, backend_search_names_thread, NULL, NULL); +} + +void pk_backend_search_names (PkBackend *backend, PkBackendJob *job, PkBitfield filters, gchar **values) +{ + pk_backend_job_thread_create(job, backend_search_names_thread, NULL, NULL); +} + +void pk_backend_search_files (PkBackend *backend, PkBackendJob *job, PkBitfield filters, gchar **values) +{ + pk_backend_job_finished (job); +} + +void pk_backend_search_groups (PkBackend *backend, PkBackendJob *job, PkBitfield filters, gchar **values) +{ + pk_backend_job_finished (job); +} + +void pk_backend_download_packages (PkBackend *backend, PkBackendJob *job, gchar **package_ids, const gchar *directory) +{ + pk_backend_job_finished (job); +} +// vim:set ts=2 :