Tuesday, 15 February 2022

Re: /boot disk partition size

diff -Nru packagekit-1.2.4/backends/alpm/meson.build packagekit-1.2.4+git20220215/backends/alpm/meson.build
--- packagekit-1.2.4/backends/alpm/meson.build 2021-07-30 01:24:45.075523000 -0700
+++ packagekit-1.2.4+git20220215/backends/alpm/meson.build 2022-02-15 11:44:24.000000000 -0800
@@ -1,4 +1,4 @@
-alpm_dep = dependency('libalpm', version: '>=12.0.0')
+alpm_dep = dependency('libalpm', version: '>=13.0.0')

shared_module(
'pk_backend_alpm',
diff -Nru packagekit-1.2.4/backends/alpm/pk-alpm-config.c packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-config.c
--- packagekit-1.2.4/backends/alpm/pk-alpm-config.c 2021-07-30 01:24:45.075523000 -0700
+++ packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-config.c 2022-02-15 11:44:24.000000000 -0800
@@ -40,14 +40,14 @@
typedef struct
{
gboolean checkspace, color, disabledownloadtimeout, ilovecandy,
- totaldl, usesyslog, verbosepkglists, is_check;
+ noprogressbar, totaldl, usesyslog, verbosepkglists, is_check;

gchar *arch, *cleanmethod, *dbpath, *gpgdir, *logfile,
*root, *xfercmd;

alpm_list_t *cachedirs, *holdpkgs, *ignoregroups,
*ignorepkgs, *localfilesiglevels, *noextracts,
- *noupgrades, *remotefilesiglevels;
+ *noupgrades, *remotefilesiglevels, *hookdirs;

alpm_list_t *sections;
GRegex *xrepo, *xarch;
@@ -106,6 +106,7 @@
FREELIST (config->noextracts);
FREELIST (config->noupgrades);
FREELIST (config->remotefilesiglevels);
+ FREELIST (config->hookdirs);

alpm_list_free_inner (config->sections, pk_alpm_config_section_free);
alpm_list_free (config->sections);
@@ -147,6 +148,14 @@
}

static void
+pk_alpm_config_set_noprogressbar (PkAlpmConfig *config)
+{
+ g_return_if_fail (config != NULL);
+
+ config->noprogressbar = TRUE;
+}
+
+static void
pk_alpm_config_set_totaldl (PkAlpmConfig *config)
{
g_return_if_fail (config != NULL);
@@ -182,6 +191,7 @@
{ "Color", pk_alpm_config_set_color },
{ "DisableDownloadTimeout", pk_alpm_config_set_disabledownloadtimeout },
{ "ILoveCandy", pk_alpm_config_set_ilovecandy },
+ { "NoProgressBar", pk_alpm_config_set_noprogressbar },
{ "TotalDownload", pk_alpm_config_set_totaldl },
{ "UseSyslog", pk_alpm_config_set_usesyslog },
{ "VerbosePkgLists", pk_alpm_config_set_verbosepkglists },
@@ -360,6 +370,7 @@
{ "NoUpgrade", G_STRUCT_OFFSET (PkAlpmConfig, noupgrades) },
{ "RemoteFileSigLevel", G_STRUCT_OFFSET (PkAlpmConfig,
remotefilesiglevels) },
+ { "HookDir", G_STRUCT_OFFSET (PkAlpmConfig, hookdirs) },
{ NULL, 0 }
};

@@ -599,6 +610,11 @@
continue;
}

+ if (g_strcmp0 (key, "ParallelDownloads") == 0 && str != NULL) {
+ /* Ignore "ParallelDownloads" key instead of crashing */
+ continue;
+ }
+
/* report errors from above */
g_set_error (&e, PK_ALPM_ERROR, PK_ALPM_ERR_CONFIG_INVALID,
"unrecognised directive '%s'", key);
@@ -635,8 +651,10 @@
}

if (config->is_check) {
+ gchar* path;
+
g_free(config->dbpath);
- gchar* path = g_strconcat (config->root,
+ path = g_strconcat (config->root,
"/var/lib/PackageKit/alpm" + dir,
NULL);
g_mkdir_with_parents(path, 0755);
@@ -791,7 +809,7 @@
pk_alpm_config_configure_repos (PkBackend *backend, PkAlpmConfig *config,
alpm_handle_t *handle, GError **error)
{
- alpm_siglevel_t base, level, mask, local, remote;
+ alpm_siglevel_t base, level = 0, mask = 0, local, remote;
const alpm_list_t *i;
PkAlpmConfigSection *options;

@@ -870,7 +888,7 @@
}

static gint
-pk_alpm_fetchcb (const gchar *url, const gchar *path, gint force)
+pk_alpm_fetchcb (void *ctx, const gchar *url, const gchar *path, gint force)
{
GRegex *xo, *xi;
gint result = 0;
@@ -942,6 +960,9 @@
{
PkBackendAlpmPrivate *priv = pk_backend_get_user_data (config->backend);
alpm_handle_t *handle;
+ gchar **arches;
+ gint i;
+ alpm_list_t *arches_list = NULL;

g_return_val_if_fail (config != NULL, FALSE);

@@ -951,7 +972,14 @@

alpm_option_set_checkspace (handle, config->checkspace);
alpm_option_set_usesyslog (handle, config->usesyslog);
- alpm_option_set_arch (handle, config->arch);
+
+ arches = g_strsplit (config->arch, ",", -1);
+ for (i = 0; arches[i]; i++) {
+ arches_list = alpm_list_add (arches_list, arches[i]);
+ }
+ alpm_option_set_architectures (handle, arches_list);
+ g_strfreev (arches);
+ alpm_list_free (arches_list);

/* backend takes ownership */
g_free (xfercmd);
@@ -959,9 +987,9 @@
config->xfercmd = NULL;

if (xfercmd != NULL) {
- alpm_option_set_fetchcb (handle, pk_alpm_fetchcb);
+ alpm_option_set_fetchcb (handle, pk_alpm_fetchcb, NULL);
} else {
- alpm_option_set_fetchcb (handle, NULL);
+ alpm_option_set_fetchcb (handle, NULL, NULL);
}

/* backend takes ownership */
@@ -985,6 +1013,10 @@
alpm_option_set_noupgrades (handle, config->noupgrades);
config->noupgrades = NULL;

+ /* alpm takes ownership */
+ alpm_option_set_noupgrades (handle, config->hookdirs);
+ config->hookdirs = NULL;
+
pk_alpm_config_configure_repos (backend, config, handle, error);

return handle;
diff -Nru packagekit-1.2.4/backends/alpm/pk-alpm-error.c packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-error.c
--- packagekit-1.2.4/backends/alpm/pk-alpm-error.c 2021-07-30 01:24:45.076522800 -0700
+++ packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-error.c 2022-02-15 11:44:24.000000000 -0800
@@ -72,7 +72,6 @@
break;
case ALPM_ERR_DB_OPEN:
case ALPM_ERR_DB_NOT_FOUND:
- case ALPM_ERR_PKG_REPO_NOT_FOUND:
code = PK_ERROR_ENUM_REPO_NOT_FOUND;
break;
case ALPM_ERR_DB_CREATE:
diff -Nru packagekit-1.2.4/backends/alpm/pk-alpm-packages.c packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-packages.c
--- packagekit-1.2.4/backends/alpm/pk-alpm-packages.c 2021-07-30 01:24:45.076522800 -0700
+++ packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-packages.c 2022-02-15 11:44:24.000000000 -0800
@@ -82,7 +82,7 @@
if (g_strcmp0 (repo_id, "installed") == 0) {
db = priv->localdb;
} else {
- const alpm_list_t *i = alpm_get_syncdbs (priv->alpm);
+ const alpm_list_t *i = alpm_get_syncdbs (priv->alpm_check ? priv->alpm_check : priv->alpm);
for (; i != NULL; i = i->next) {
const gchar *repo = alpm_db_get_name (i->data);

diff -Nru packagekit-1.2.4/backends/alpm/pk-alpm-search.c packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-search.c
--- packagekit-1.2.4/backends/alpm/pk-alpm-search.c 2021-07-30 01:24:45.076522800 -0700
+++ packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-search.c 2022-02-15 11:44:24.000000000 -0800
@@ -414,7 +414,7 @@
if (skip_remote)
goto out;

- for (i = alpm_get_syncdbs (priv->alpm); i != NULL; i = i->next) {
+ for (i = alpm_get_syncdbs (priv->alpm_check ? priv->alpm_check : priv->alpm); i != NULL; i = i->next) {
if (pk_backend_job_is_cancelled (job))
break;

diff -Nru packagekit-1.2.4/backends/alpm/pk-alpm-sync.c packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-sync.c
--- packagekit-1.2.4/backends/alpm/pk-alpm-sync.c 2021-07-30 01:24:45.076522800 -0700
+++ packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-sync.c 2022-02-15 11:44:24.000000000 -0800
@@ -30,6 +30,7 @@
#include "pk-alpm-error.h"
#include "pk-alpm-transaction.h"
#include "pk-alpm-update.h"
+#include "pk-alpm-packages.h"

static gboolean
pk_alpm_transaction_sync_targets (PkBackendJob *job, const gchar **packages, gboolean update, GError **error)
@@ -60,18 +61,27 @@
}

pkg = alpm_db_get_pkg (i->data, name);
+ alpm_pkg_t *dep_to_remove = pk_alpm_pkg_replaces(priv->localdb, pkg);
+ if (dep_to_remove) {
+ g_debug("scheduling to remove %s for %s", alpm_pkg_get_name(dep_to_remove), name);
+ alpm_remove_pkg(priv->alpm, dep_to_remove);
+ }

if (update) { // libalpm only checks for ignorepkgs on an update
const alpm_list_t *ignorepkgs, *ignoregroups, *group_iter;

ignorepkgs = alpm_option_get_ignorepkgs (priv->alpm);
- if (alpm_list_find_str (ignorepkgs, alpm_pkg_get_name (pkg)) != NULL)
+ if (alpm_list_find_str (ignorepkgs, alpm_pkg_get_name (pkg)) != NULL) {
+ pk_alpm_pkg_emit(job, pkg, PK_INFO_ENUM_BLOCKED);
goto cont;
+ }

ignoregroups = alpm_option_get_ignoregroups (priv->alpm);
for (group_iter = alpm_pkg_get_groups (pkg); group_iter != NULL; group_iter = group_iter->next) {
- if (alpm_list_find_str (ignoregroups, i->data) != NULL)
- pk_alpm_pkg_emit (job, pkg, PK_INFO_ENUM_BLOCKED); goto cont;
+ if (alpm_list_find_str (ignoregroups, i->data) != NULL) {
+ pk_alpm_pkg_emit (job, pkg, PK_INFO_ENUM_BLOCKED);
+ goto cont;
+ }
}
}

@@ -176,7 +186,7 @@
PkBackendAlpmPrivate *priv = pk_backend_get_user_data (backend);
PkBitfield flags;
gboolean only_trusted;
- const alpm_list_t *i;
+ alpm_list_t *i;
alpm_list_t *asdeps = NULL, *asexplicit = NULL;
alpm_transflag_t alpm_flags = 0;
const gchar** package_ids;
@@ -188,11 +198,10 @@
if (!only_trusted && !pk_alpm_disable_signatures (backend, &error))
goto out;

- if ((gboolean)p) {
+ if (p) {
i = alpm_get_syncdbs(priv->alpm);
- for (; i != NULL; i = i->next) {
- pk_alpm_update_database(job, TRUE, i->data, &error);
- }
+ pk_alpm_refresh_databases (job, TRUE, i, &error);
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_QUERY);
}

/* download only */
@@ -200,7 +209,7 @@
alpm_flags |= ALPM_TRANS_FLAG_DOWNLOADONLY;

if (pk_alpm_transaction_initialize (job, alpm_flags, NULL, &error) &&
- pk_alpm_transaction_sync_targets (job, package_ids, (gboolean)p, &error) &&
+ pk_alpm_transaction_sync_targets (job, package_ids, p ? TRUE : FALSE, &error) &&
pk_alpm_transaction_simulate (job, &error)) {

if (pk_bitfield_contain (flags, PK_TRANSACTION_FLAG_ENUM_SIMULATE)) { /* simulation */
@@ -263,7 +272,7 @@
PkBitfield transaction_flags,
gchar **package_ids)
{
- pk_alpm_run (job, PK_STATUS_ENUM_SETUP, pk_backend_sync_thread, TRUE);
+ pk_alpm_run (job, PK_STATUS_ENUM_SETUP, pk_backend_sync_thread, (void *)TRUE);
}

void
diff -Nru packagekit-1.2.4/backends/alpm/pk-alpm-transaction.c packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-transaction.c
--- packagekit-1.2.4/backends/alpm/pk-alpm-transaction.c 2021-07-30 01:24:45.076522800 -0700
+++ packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-transaction.c 2022-02-15 11:44:24.000000000 -0800
@@ -53,9 +53,6 @@
static gboolean
pk_alpm_pkg_has_basename (PkBackend *backend, alpm_pkg_t *pkg, const gchar *basename)
{
- PkBackendAlpmPrivate *priv = pk_backend_get_user_data (backend);
- const alpm_list_t *i;
-
g_return_val_if_fail (pkg != NULL, FALSE);
g_return_val_if_fail (basename != NULL, FALSE);

@@ -130,74 +127,56 @@
}

static void
-pk_alpm_transaction_totaldlcb (off_t total)
-{
- PkBackendJob* job;
- g_assert (pkalpm_current_job);
- job = pkalpm_current_job;
-
- if (transaction_dtotal > 0 && dpkg != NULL)
- pk_alpm_transaction_download_end (job);
-
- transaction_dcomplete = 0;
- transaction_dtotal = total;
-}
-
-static void
-pk_alpm_transaction_dlcb (const gchar *basename, off_t complete, off_t total)
+pk_alpm_transaction_dlcb (void *ctx, const gchar *filename, alpm_download_event_type_t type, void *data)
{
guint percentage = 100, sub_percentage = 100;
+ alpm_download_event_completed_t *completed = data;
+ alpm_download_event_progress_t *progress = data;

PkBackendJob* job;
g_assert (pkalpm_current_job);
job = pkalpm_current_job;

- g_return_if_fail(basename != NULL);
-
- // these conditions are documented in libalpm/dload.c
- if (complete == 0 && total == -1) { // initialized download
- g_debug ("downloading file %s", basename);
+ g_return_if_fail (filename != NULL);
+ switch (type) {
+ case ALPM_DOWNLOAD_INIT:
pk_backend_job_set_status (job, PK_STATUS_ENUM_DOWNLOAD);
- pk_alpm_transaction_download_start (job, basename);
-
- } else if (complete == 0 && total == 0) { // doing non-download event
- return;
+ pk_alpm_transaction_download_start (job, filename);
+ break;

- } else if (complete > 0 && complete == total) { // download is complete
- pk_backend_job_set_percentage(job, 100);
- transaction_dcomplete += complete;
+ case ALPM_DOWNLOAD_COMPLETED:
+ pk_backend_job_set_percentage (job, 100);
+ transaction_dcomplete += completed->total;
+ break;

- } else if (complete > 0 && complete < total && total > 0) { // download in progress
- sub_percentage = (complete * 100) / (total);
+ case ALPM_DOWNLOAD_PROGRESS:
if (transaction_dtotal > 0) {
- // positive totals indicate packages
- percentage = ((transaction_dcomplete + complete) * 100) / transaction_dtotal;
-
+ transaction_dcomplete += progress->downloaded;
+ percentage = ((transaction_dcomplete + progress->downloaded) * 100) / transaction_dtotal;
pk_backend_job_set_percentage (job, percentage);
} else if (transaction_dtotal < 0) {
- // negative totals indicate databases
- guint total_databases = -transaction_dtotal;
static off_t previous_total = 0;
static guint current_database = 0;
+ guint total_databases = -transaction_dtotal;

- if (total != previous_total) {
+ if (progress->total != previous_total) {
current_database++;
- previous_total = total;
+ previous_total = progress->total;
}

- percentage = ((current_database-1)*100) / total_databases;
+ percentage = ((current_database - 1) * 100) / total_databases;
percentage += sub_percentage / total_databases;

pk_backend_job_set_percentage (job, percentage);
}
-
- } else {
+ break;
+ default:
syslog (LOG_DAEMON | LOG_WARNING, "unhandled download callback case, most likely libalpm change or error");
}
}

static void
-pk_alpm_transaction_progress_cb (alpm_progress_t type, const gchar *target,
+pk_alpm_transaction_progress_cb (void *ctx, alpm_progress_t type, const gchar *target,
gint percent, gsize targets, gsize current)
{
static gint recent = 101;
@@ -264,7 +243,7 @@
if (percent == recent)
break;

- pk_backend_job_set_item_progress (job, target, PK_ROLE_ENUM_UNKNOWN, percent);
+ pk_backend_job_set_item_progress (job, target, PK_STATUS_ENUM_UNKNOWN, percent);
pk_backend_job_set_percentage (job, overall / targets);
recent = percent;

@@ -291,7 +270,9 @@
output = g_strdup_printf ("%s: was not ignored\n",
alpm_pkg_get_name (q->pkg));
pk_alpm_transaction_output (output);
-
+#if (!defined(__clang__)) && (__GNUC__ >= 7)
+ __attribute__ ((fallthrough)); /* let's be explicit about falltrhough */
+#endif
case PK_ROLE_ENUM_DOWNLOAD_PACKAGES:
q->install = 1;
break;
@@ -319,7 +300,7 @@
}

static void
-pk_alpm_transaction_conv_cb (alpm_question_t *question)
+pk_alpm_transaction_conv_cb (void *ctx, alpm_question_t *question)
{
PkBackendJob* job;
g_assert (pkalpm_current_job);
@@ -634,12 +615,6 @@
}

static void
-pk_alpm_transaction_repackaging (PkBackendJob *job)
-{
- pk_backend_job_set_status (job, PK_STATUS_ENUM_REPACKAGING);
-}
-
-static void
pk_alpm_transaction_download (PkBackendJob *job)
{
pk_backend_job_set_status (job, PK_STATUS_ENUM_DOWNLOAD);
@@ -665,7 +640,7 @@
}

static void
-pk_alpm_transaction_event_cb (alpm_event_t *event)
+pk_alpm_transaction_event_cb (void *ctx, alpm_event_t *event)
{
PkBackendJob* job;
job = pkalpm_current_job;
@@ -733,7 +708,7 @@
pk_alpm_transaction_output (((alpm_event_scriptlet_info_t *) event)->line);
break;
case ALPM_EVENT_KEY_DOWNLOAD_START:
- case ALPM_EVENT_RETRIEVE_START:
+ case ALPM_EVENT_DB_RETRIEVE_START:
pk_alpm_transaction_download (job);
break;
case ALPM_EVENT_OPTDEP_REMOVAL:
@@ -762,12 +737,12 @@
case ALPM_EVENT_LOAD_DONE:
case ALPM_EVENT_PACNEW_CREATED:
case ALPM_EVENT_PACSAVE_CREATED:
- case ALPM_EVENT_PKGDOWNLOAD_DONE:
- case ALPM_EVENT_PKGDOWNLOAD_FAILED:
- case ALPM_EVENT_PKGDOWNLOAD_START:
+ case ALPM_EVENT_PKG_RETRIEVE_DONE:
+ case ALPM_EVENT_PKG_RETRIEVE_FAILED:
+ case ALPM_EVENT_PKG_RETRIEVE_START:
case ALPM_EVENT_RESOLVEDEPS_DONE:
- case ALPM_EVENT_RETRIEVE_DONE:
- case ALPM_EVENT_RETRIEVE_FAILED:
+ case ALPM_EVENT_DB_RETRIEVE_DONE:
+ case ALPM_EVENT_DB_RETRIEVE_FAILED:
case ALPM_EVENT_TRANSACTION_DONE:
case ALPM_EVENT_TRANSACTION_START:
/* ignored */
@@ -804,12 +779,11 @@
pkalpm_current_job = job;
pkalpm_dirname = dirname;

- alpm_option_set_eventcb (priv->alpm, pk_alpm_transaction_event_cb);
- alpm_option_set_questioncb (priv->alpm, pk_alpm_transaction_conv_cb);
- alpm_option_set_progresscb (priv->alpm, pk_alpm_transaction_progress_cb);
+ alpm_option_set_eventcb (priv->alpm, pk_alpm_transaction_event_cb, NULL);
+ alpm_option_set_questioncb (priv->alpm, pk_alpm_transaction_conv_cb, NULL);
+ alpm_option_set_progresscb (priv->alpm, pk_alpm_transaction_progress_cb, NULL);

- alpm_option_set_dlcb (priv->alpm, pk_alpm_transaction_dlcb);
- alpm_option_set_totaldlcb (priv->alpm, pk_alpm_transaction_totaldlcb);
+ alpm_option_set_dlcb (priv->alpm, pk_alpm_transaction_dlcb, NULL);

g_cancellable_connect (pk_backend_job_get_cancellable (job),
G_CALLBACK (pk_alpm_transaction_cancelled_cb),
@@ -1123,12 +1097,12 @@
PkBackend *backend = pk_backend_job_get_backend (job);
PkBackendAlpmPrivate *priv = pk_backend_get_user_data (backend);

- alpm_option_set_eventcb (priv->alpm, NULL);
- alpm_option_set_questioncb (priv->alpm, NULL);
- alpm_option_set_progresscb (priv->alpm, NULL);
+ alpm_option_set_eventcb (priv->alpm, NULL, NULL);
+ alpm_option_set_questioncb (priv->alpm, NULL, NULL);
+ alpm_option_set_progresscb (priv->alpm, NULL, NULL);

- alpm_option_set_dlcb (priv->alpm, NULL);
- alpm_option_set_totaldlcb (priv->alpm, NULL);
+ alpm_option_set_dlcb (priv->alpm, NULL, NULL);
+// alpm_option_set_totaldlcb (priv->alpm, NULLa;

if (dpkg != NULL)
pk_alpm_transaction_download_end (job);
diff -Nru packagekit-1.2.4/backends/alpm/pk-alpm-update.c packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-update.c
--- packagekit-1.2.4/backends/alpm/pk-alpm-update.c 2021-07-30 01:24:45.077523000 -0700
+++ packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-update.c 2022-02-15 11:44:24.000000000 -0800
@@ -39,33 +39,32 @@
#include "pk-alpm-transaction.h"
#include "pk-alpm-update.h"

-static gchar *
+static gchar **
pk_alpm_pkg_build_replaces (PkBackendJob *job, alpm_pkg_t *pkg)
{
PkBackend *backend = pk_backend_job_get_backend (job);
PkBackendAlpmPrivate *priv = pk_backend_get_user_data (backend);
const alpm_list_t *i;
- GString *string = NULL;
+ gchar **replaces = NULL;
+ gint count = 0;

g_return_val_if_fail (pkg != NULL, NULL);

/* make a list of the packages that package replaces */
for (i = alpm_pkg_get_replaces (pkg); i != NULL; i = i->next) {
- alpm_pkg_t *replaces = alpm_db_get_pkg (priv->localdb, i->data);
+ alpm_pkg_t *package = alpm_db_get_pkg (priv->localdb, i->data);

- if (replaces != NULL) {
- g_autofree gchar *package = pk_alpm_pkg_build_id (replaces);
- if (string == NULL) {
- string = g_string_new (package);
- } else {
- g_string_append_printf (string, "&%s", package);
+ if (package != NULL) {
+ gchar *id = pk_alpm_pkg_build_id (package);
+ if (id) {
+ replaces = g_realloc (replaces, ((++count) + 1) * sizeof(gchar *));
+ replaces[count - 1] = id;
+ replaces[count] = NULL;
}
}
}

- if (string == NULL)
- return NULL;
- return g_string_free (string, FALSE);
+ return replaces;
}

static gchar **
@@ -143,8 +142,9 @@
PkRestartEnum restart = PK_RESTART_ENUM_NONE;
PkUpdateStateEnum state = PK_UPDATE_STATE_ENUM_STABLE;
alpm_time_t built, installed;
- g_autofree gchar *upgrades = NULL;
- g_autofree gchar *replaces = NULL;
+ gchar *upgrades[2] = { NULL, NULL };
+ gchar **replaces;
+ gchar **charptr;
g_auto(GStrv) urls = NULL;
g_autofree gchar *issued = NULL;
g_autofree gchar *updated = NULL;
@@ -158,7 +158,7 @@

old = alpm_db_get_pkg (priv->localdb, alpm_pkg_get_name (pkg));
if (old != NULL) {
- upgrades = pk_alpm_pkg_build_id (old);
+ upgrades[0] = pk_alpm_pkg_build_id (old);
if (pk_alpm_pkg_same_pkgver (pkg, old)) {
reason = "Update to a newer release";
} else {
@@ -182,16 +182,22 @@
if (built > 0)
issued = pk_alpm_time_to_iso8601 (built);

- if (upgrades != NULL) {
+ if (upgrades[0] != NULL) {
installed = alpm_pkg_get_installdate (old);
if (installed > 0)
updated = pk_alpm_time_to_iso8601 (installed);
}

- pk_backend_job_update_detail (job, *packages, &upgrades,
- &replaces, urls, NULL, NULL,
+ pk_backend_job_update_detail (job, *packages, upgrades,
+ replaces, urls, NULL, NULL,
restart, reason, NULL, state,
issued, updated);
+ if (upgrades[0]) g_free (upgrades[0]);
+ if (replaces) {
+ for (charptr = replaces; charptr[0]; charptr++)
+ g_free (charptr[0]);
+ g_free(replaces);
+ }
}

pk_alpm_finish (job, error);
@@ -215,26 +221,6 @@
}

static gboolean
-pk_alpm_update_is_db_fresh (PkBackendJob *job, alpm_db_t *db)
-{
- guint cache_age;
- GStatBuf stat_buffer;
- g_autofree gchar *timestamp_filename = NULL;
-
- cache_age = pk_backend_job_get_cache_age (job);
-
- timestamp_filename = pk_alpm_update_get_db_timestamp_filename (db);
-
- if (cache_age < 0 || cache_age >= G_MAXUINT)
- return FALSE;
-
- if (g_stat (timestamp_filename, &stat_buffer) < 0)
- return FALSE;
-
- return stat_buffer.st_mtime >= (time (NULL) - cache_age);
-}
-
-static gboolean
pk_alpm_update_set_db_timestamp (alpm_db_t *db, GError **error)
{
g_autofree gchar *timestamp_filename = NULL;
@@ -263,32 +249,34 @@
}

gboolean
-pk_alpm_update_database (PkBackendJob *job, gint force, alpm_db_t *db, GError **error)
+pk_alpm_refresh_databases (PkBackendJob *job, gint force, alpm_list_t *dbs, GError **error)
{
PkBackend *backend = pk_backend_job_get_backend (job);
PkBackendAlpmPrivate *priv = pk_backend_get_user_data (backend);
- alpm_cb_download dlcb;
gint result;
-
- dlcb = alpm_option_get_dlcb (priv->alpm);
-
- if (pk_alpm_update_is_db_fresh (job, db))
- return TRUE;
+ alpm_list_t *i;

if (!force)
return TRUE;

- result = alpm_db_update (force, db);
- if (result > 0) {
- dlcb ("", 1, 1);
- } else if (result < 0) {
- g_set_error (error, PK_ALPM_ERROR, alpm_errno (priv->alpm), "[%s]: %s",
- alpm_db_get_name (db),
+ if (priv->alpm != priv->alpm_check) {
+ // We can now discard the check db as the main db is more up to date again
+ alpm_release(priv->alpm_check);
+ priv->alpm_check = NULL;
+ }
+ result = alpm_db_update (priv->alpm, dbs, force);
+ if (result < 0) {
+ g_set_error (error, PK_ALPM_ERROR, alpm_errno (priv->alpm), "failed to uptate database: %s",
alpm_strerror (errno));
return FALSE;
}

- return pk_alpm_update_set_db_timestamp (db, error);
+ for (i = dbs; i; i = alpm_list_next (i)) {
+ if (!pk_alpm_update_set_db_timestamp (i->data, error)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
}

static gboolean
@@ -296,9 +284,7 @@
{
PkBackend *backend = pk_backend_job_get_backend (job);
PkBackendAlpmPrivate *priv = pk_backend_get_user_data (backend);
- alpm_cb_totaldl totaldlcb;
- gboolean ret;
- const alpm_list_t *i;
+ alpm_list_t *i;

if (!pk_alpm_transaction_initialize (job, 0, NULL, error))
return FALSE;
@@ -306,31 +292,13 @@
alpm_logaction (priv->alpm, PK_LOG_PREFIX, "synchronizing package lists\n");
pk_backend_job_set_status (job, PK_STATUS_ENUM_DOWNLOAD_PACKAGELIST);

- totaldlcb = alpm_option_get_totaldlcb (priv->alpm);
-
- /* set total size to minus the number of databases */
i = alpm_get_syncdbs (priv->alpm);
- totaldlcb (-alpm_list_count (i));
-
- for (; i != NULL; i = i->next) {
- if (pk_backend_job_is_cancelled (job)) {
- /* pretend to be finished */
- i = NULL;
- break;
- }
-
- ret = pk_alpm_update_database (job, force, i->data, error);
- if (!ret) {
- break;
- }
- }
-
- totaldlcb (0);
+ int ret = pk_alpm_refresh_databases(job, force, i, error);

if (i == NULL)
return pk_alpm_transaction_end (job, error);
pk_alpm_transaction_end (job, NULL);
- return FALSE;
+ return ret != 0;
}

static gboolean
@@ -363,13 +331,42 @@
return FALSE;
}

-static gboolean
-pk_alpm_pkg_replaces (alpm_pkg_t *pkg, const gchar *name)
+static int dep_vercmp(const char *version1, alpm_depmod_t mod,
+ const char *version2)
{
+ int equal = 0;
+
+ if(mod == ALPM_DEP_MOD_ANY) {
+ equal = 1;
+ } else {
+ int cmp = alpm_pkg_vercmp(version1, version2);
+ switch(mod) {
+ case ALPM_DEP_MOD_EQ: equal = (cmp == 0); break;
+ case ALPM_DEP_MOD_GE: equal = (cmp >= 0); break;
+ case ALPM_DEP_MOD_LE: equal = (cmp <= 0); break;
+ case ALPM_DEP_MOD_LT: equal = (cmp < 0); break;
+ case ALPM_DEP_MOD_GT: equal = (cmp > 0); break;
+ default: equal = 1; break;
+ }
+ }
+ return equal;
+}
+
+alpm_pkg_t *
+pk_alpm_pkg_replaces (alpm_db_t *db, alpm_pkg_t *pkg)
+{
+ g_return_val_if_fail (db != NULL, FALSE);
g_return_val_if_fail (pkg != NULL, FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
+ gboolean ret = FALSE;

- return alpm_list_find_str (alpm_pkg_get_replaces (pkg), name) != NULL;
+ for (alpm_list_t *list = alpm_pkg_get_replaces (pkg); list != NULL && !ret; list = list->next) {
+ alpm_depend_t *depend = list->data;
+ alpm_pkg_t *deppkg = alpm_db_get_pkg(db, depend->name);
+ if (deppkg && dep_vercmp(alpm_pkg_get_version(deppkg), depend->mod, depend->version)) {
+ return deppkg;
+ }
+ }
+ return NULL;
}

static alpm_pkg_t *
@@ -392,12 +389,6 @@
}
return NULL;
}
-
- i = alpm_db_get_pkgcache (dbs->data);
- for (; i != NULL; i = i->next) {
- if (pk_alpm_pkg_replaces (i->data, name))
- return i->data;
- }
}

return NULL;
@@ -425,14 +416,13 @@
PkBackend *backend = pk_backend_job_get_backend (job);
PkBackendAlpmPrivate *priv = pk_backend_get_user_data (backend);
int update_count = 0;
- const alpm_list_t *i, *syncdbs;
+ alpm_list_t *i, *syncdbs;
g_autoptr(GError) error = NULL;
PkBitfield filters = 0;
FILE *file;
int stored_count;
- alpm_cb_totaldl totaldlcb;
- gboolean ret;
- alpm_handle_t* handle = pk_alpm_configure (backend, PK_BACKEND_CONFIG_FILE, TRUE, error);
+ alpm_handle_t* old_handle = priv->alpm;
+ alpm_handle_t* handle = priv->alpm_check ? priv->alpm_check : pk_alpm_configure (backend, PK_BACKEND_CONFIG_FILE, TRUE, &error);

alpm_logaction (handle, PK_LOG_PREFIX, "synchronizing package lists\n");
pk_backend_job_set_status (job, PK_STATUS_ENUM_DOWNLOAD_PACKAGELIST);
@@ -440,17 +430,12 @@
/* set total size to minus the number of databases */
i = alpm_get_syncdbs (handle);

- for (; i != NULL; i = i->next) {
- if (pk_backend_job_is_cancelled (job)) {
- /* pretend to be finished */
- i = NULL;
- break;
- }
-
- ret = pk_alpm_update_database (job, TRUE, i->data, error);
- if (!ret)
- break;
- }
+ // swap around the handles since the refresh database will grab
+ // the main system handle and not the check update handle otherwise
+ priv->alpm = handle;
+ pk_alpm_refresh_databases (job, TRUE, i, &error);
+ priv->alpm = old_handle;
+ priv->alpm_check = handle;

if (pk_backend_job_get_role (job) == PK_ROLE_ENUM_GET_UPDATES) {
g_variant_get (params, "(t)", &filters);
diff -Nru packagekit-1.2.4/backends/alpm/pk-alpm-update.h packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-update.h
--- packagekit-1.2.4/backends/alpm/pk-alpm-update.h 2021-07-30 01:24:45.077523000 -0700
+++ packagekit-1.2.4+git20220215/backends/alpm/pk-alpm-update.h 2022-02-15 11:44:24.000000000 -0800
@@ -23,4 +23,8 @@
#include <alpm.h>
#include <pk-backend.h>

-gboolean pk_alpm_update_database(PkBackendJob *job, gint force, alpm_db_t *db, GError **error);
+gboolean pk_alpm_refresh_databases (PkBackendJob *job, gint force,
+ alpm_list_t *dbs, GError **error);
+
+alpm_pkg_t *
+pk_alpm_pkg_replaces (alpm_db_t *db, alpm_pkg_t *pkg);
diff -Nru packagekit-1.2.4/backends/alpm/pk-backend-alpm.c packagekit-1.2.4+git20220215/backends/alpm/pk-backend-alpm.c
--- packagekit-1.2.4/backends/alpm/pk-backend-alpm.c 2021-07-30 01:24:45.077523000 -0700
+++ packagekit-1.2.4+git20220215/backends/alpm/pk-backend-alpm.c 2022-02-15 11:44:24.000000000 -0800
@@ -51,7 +51,7 @@
}

static void
-pk_alpm_logcb (alpm_loglevel_t level, const gchar *format, va_list args)
+pk_alpm_logcb (void *ctx, alpm_loglevel_t level, const gchar *format, va_list args)
{
g_autofree gchar *output = NULL;

@@ -86,7 +86,8 @@
return FALSE;
}

- alpm_option_set_logcb (priv->alpm, pk_alpm_logcb);
+ priv->alpm_check = NULL;
+ alpm_option_set_logcb (priv->alpm, pk_alpm_logcb, NULL);

priv->localdb = alpm_get_localdb (priv->alpm);
if (priv->localdb == NULL) {
diff -Nru packagekit-1.2.4/backends/alpm/pk-backend-alpm.h packagekit-1.2.4+git20220215/backends/alpm/pk-backend-alpm.h
--- packagekit-1.2.4/backends/alpm/pk-backend-alpm.h 2021-07-30 01:24:45.077523000 -0700
+++ packagekit-1.2.4+git20220215/backends/alpm/pk-backend-alpm.h 2022-02-15 11:44:24.000000000 -0800
@@ -30,6 +30,7 @@
alpm_list_t *syncfirsts;
alpm_list_t *holdpkgs;
alpm_handle_t *alpm;
+ alpm_handle_t *alpm_check;
GFileMonitor *monitor;
alpm_list_t *configured_repos; /* list of configured repos */
gboolean localdb_changed;
diff -Nru packagekit-1.2.4/backends/aptcc/apt-cache-file.cpp packagekit-1.2.4+git20220215/backends/aptcc/apt-cache-file.cpp
--- packagekit-1.2.4/backends/aptcc/apt-cache-file.cpp 2021-07-30 01:24:45.077523000 -0700
+++ packagekit-1.2.4+git20220215/backends/aptcc/apt-cache-file.cpp 2022-02-15 11:44:24.000000000 -0800
@@ -1,5 +1,5 @@
/* apt-cache-file.cpp
- *
+ *
* Copyright (c) 2012 Daniel Nicoletti <dantti12@gmail.com>
* Copyright (c) 2012 Matthias Klumpp <matthias@tenstral.net>
* Copyright (c) 2016 Harald Sitter <sitter@kde.org>
@@ -248,7 +248,7 @@
pk_backend_job_error_code(m_job,
error,
"%s",
- utf8(out.str().c_str()));
+ toUtf8(out.str().c_str()));
}

void AptCacheFile::buildPkgRecords()
@@ -355,39 +355,66 @@
return false;
}

-pkgCache::VerIterator AptCacheFile::resolvePkgID(const gchar *packageId)
+PkgInfo AptCacheFile::resolvePkgID(const gchar *packageId)
{
- gchar **parts;
+ g_auto(GStrv) parts = nullptr;
pkgCache::PkgIterator pkg;

parts = pk_package_id_split(packageId);
pkg = (*this)->FindPkg(parts[PK_PACKAGE_ID_NAME], parts[PK_PACKAGE_ID_ARCH]);

// Ignore packages that could not be found or that exist only due to dependencies.
- if (pkg.end() || (pkg.VersionList().end() && pkg.ProvidesList().end())) {
- g_strfreev(parts);
- return pkgCache::VerIterator();
- }
+ if (pkg.end() || (pkg.VersionList().end() && pkg.ProvidesList().end()))
+ return PkgInfo(pkgCache::VerIterator());
+
+ // check if any intended action was encoded in this package-ID
+ auto piAction = PkgAction::NONE;
+ if (g_str_has_prefix(parts[PK_PACKAGE_ID_DATA], "+auto:"))
+ piAction = PkgAction::INSTALL_AUTO;
+ else if (g_str_has_prefix(parts[PK_PACKAGE_ID_DATA], "+manual:"))
+ piAction = PkgAction::INSTALL_MANUAL;

const pkgCache::VerIterator &ver = findVer(pkg);
// check to see if the provided package isn't virtual too
if (ver.end() == false &&
- strcmp(ver.VerStr(), parts[PK_PACKAGE_ID_VERSION]) == 0) {
- g_strfreev(parts);
- return ver;
- }
+ strcmp(ver.VerStr(), parts[PK_PACKAGE_ID_VERSION]) == 0)
+ return PkgInfo(ver, piAction);

const pkgCache::VerIterator &candidateVer = findCandidateVer(pkg);
// check to see if the provided package isn't virtual too
if (candidateVer.end() == false &&
- strcmp(candidateVer.VerStr(), parts[PK_PACKAGE_ID_VERSION]) == 0) {
- g_strfreev(parts);
- return candidateVer;
- }
+ strcmp(candidateVer.VerStr(), parts[PK_PACKAGE_ID_VERSION]) == 0)
+ return PkgInfo(candidateVer, piAction);
+
+ return PkgInfo(ver, piAction);
+}
+
+gchar *AptCacheFile::buildPackageId(const pkgCache::VerIterator &ver)
+{
+ pkgCache::VerFileIterator vf = ver.FileList();
+ const pkgCache::PkgIterator &pkg = ver.ParentPkg();
+ pkgDepCache::StateCache &State = (*this)[pkg];

- g_strfreev (parts);
+ const bool isInstalled = (pkg->CurrentState == pkgCache::State::Installed && pkg.CurrentVer() == ver);
+ const bool isAuto = (State.CandidateVer != 0) && (State.Flags & pkgCache::Flag::Auto);

- return ver;
+ // when a package is installed manually, the data part of a package-id is "manual:<repo-id>",
+ // otherwise it is "auto:<repo-id>". Available (not installed) packages have no prefix, unless
+ // a pending installation is marked, in which case we prefix the desired new mode of the installed
+ // package (auto/manual) with a plus sign (+).
+ string data = "";
+ if (isInstalled) {
+ data = isAuto? "auto:" : "manual:";
+ } else {
+ if (State.NewInstall())
+ data = isAuto? "+auto:" : "+manual:";
+ }
+ data += utilBuildPackageOriginId(vf);
+
+ return pk_package_id_build(ver.ParentPkg().Name(),
+ ver.VerStr(),
+ ver.Arch(),
+ data.c_str());
}

pkgCache::VerIterator AptCacheFile::findVer(const pkgCache::PkgIterator &pkg)
@@ -457,15 +484,15 @@
}

bool AptCacheFile::tryToInstall(pkgProblemResolver &Fix,
- const pkgCache::VerIterator &ver,
+ const PkgInfo &pki,
bool BrokenFix,
bool autoInst,
bool preserveAuto)
{
- pkgCache::PkgIterator Pkg = ver.ParentPkg();
+ pkgCache::PkgIterator Pkg = pki.ver.ParentPkg();

// Check if there is something at all to install
- GetDepCache()->SetCandidateVersion(ver);
+ GetDepCache()->SetCandidateVersion(pki.ver);
pkgDepCache::StateCache &State = (*this)[Pkg];

if (State.CandidateVer == 0) {
@@ -476,10 +503,21 @@
return false;
}

- // On updates we want to always preserve the autoflag as updates are usually
- // non-indicative of whether or not the user explicitly wants this package to be
- // installed or simply wants it to be updated.
- const bool fromUser = preserveAuto ? !(State.Flags & pkgCache::Flag::Auto) : true;
+ // Always install as "automatic" or "manual" if the package is explicitly set to
+ // either of the modes (because it may have been resolved in a previous transaction
+ // to be marked as automatic, for example in updates)
+ // If the package indicates no explicit preference we keep the current state
+ // unless the package should explicitly be marked as manually installed
+ // (via preserveAuto == false).
+ // See https://github.com/PackageKit/PackageKit/issues/450 for details.
+ bool fromUser = false;
+ if (pki.action == PkgAction::INSTALL_AUTO)
+ fromUser = false;
+ else if (pki.action == PkgAction::INSTALL_MANUAL)
+ fromUser = true;
+ else
+ fromUser = preserveAuto ? !(State.Flags & pkgCache::Flag::Auto) : true;
+
// FIXME: this is ignoring the return value. OTOH the return value means little to us
// since we run markinstall twice, once without autoinst and once with.
// We probably should change the return value behavior and have the callee decide whether to
@@ -494,9 +532,9 @@
}

void AptCacheFile::tryToRemove(pkgProblemResolver &Fix,
- const pkgCache::VerIterator &ver)
+ const PkgInfo &pki)
{
- pkgCache::PkgIterator Pkg = ver.ParentPkg();
+ pkgCache::PkgIterator Pkg = pki.ver.ParentPkg();

// The package is not installed
if (Pkg->CurrentVer == 0) {
diff -Nru packagekit-1.2.4/backends/aptcc/apt-cache-file.h packagekit-1.2.4+git20220215/backends/aptcc/apt-cache-file.h
--- packagekit-1.2.4/backends/aptcc/apt-cache-file.h 2021-07-30 01:24:45.077523000 -0700
+++ packagekit-1.2.4+git20220215/backends/aptcc/apt-cache-file.h 2022-02-15 11:44:24.000000000 -0800
@@ -27,6 +27,8 @@
#include <apt-pkg/progress.h>
#include <pk-backend.h>

+#include "pkg-list.h"
+
class pkgProblemResolver;
class AptCacheFile : public pkgCacheFile
{
@@ -102,9 +104,15 @@

/**
* Tries to find a package with the given packageId
- * @returns pkgCache::VerIterator, if .end() is true the package could not be found
+ * @returns PkgInfo containing a pkgCache::VerIterator. If PkgInfo::ver::end() is true, the package could not be found
*/
- pkgCache::VerIterator resolvePkgID(const gchar *packageId);
+ PkgInfo resolvePkgID(const gchar *packageId);
+
+ /**
+ * Build a package id from the given package version
+ * The caller must g_free the returned value
+ */
+ gchar* buildPackageId(const pkgCache::VerIterator &ver);

/**
* Tries to find the candidate version of a package
@@ -136,11 +144,11 @@
std::string getLongDescriptionParsed(const pkgCache::VerIterator &ver);

bool tryToInstall(pkgProblemResolver &Fix,
- const pkgCache::VerIterator &ver,
+ const PkgInfo &pki,
bool BrokenFix, bool autoInst, bool preserveAuto);

void tryToRemove(pkgProblemResolver &Fix,
- const pkgCache::VerIterator &ver);
+ const PkgInfo &pki);

private:
void buildPkgRecords();
diff -Nru packagekit-1.2.4/backends/aptcc/apt-intf.cpp packagekit-1.2.4+git20220215/backends/aptcc/apt-intf.cpp
--- packagekit-1.2.4/backends/aptcc/apt-intf.cpp 2021-07-30 01:24:45.078523000 -0700
+++ packagekit-1.2.4+git20220215/backends/aptcc/apt-intf.cpp 2022-02-15 11:44:24.000000000 -0800
@@ -3,7 +3,7 @@
* Copyright (c) 1999-2008 Daniel Burrows
* Copyright (c) 2004 Michael Vogt <mvo@debian.org>
* 2009-2018 Daniel Nicoletti <dantti12@gmail.com>
- * 2012-2015 Matthias Klumpp <matthias@tenstral.net>
+ * 2012-2022 Matthias Klumpp <matthias@tenstral.net>
* 2016 Harald Sitter <sitter@kde.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -94,7 +94,7 @@
}

// Check if we should open the Cache with lock
- bool withLock;
+ bool withLock = false;
bool AllowBroken = false;
PkRoleEnum role = pk_backend_job_get_role(m_job);
switch (role) {
@@ -215,9 +215,8 @@
bool installed = false;

// Check if the package is installed
- if (pkg->CurrentState == pkgCache::State::Installed && pkg.CurrentVer() == ver) {
+ if (pkg->CurrentState == pkgCache::State::Installed && pkg.CurrentVer() == ver)
installed = true;
- }

// if we are on multiarch check also the arch filter
if (m_isMultiArch && pk_bitfield_contain(filters, PK_FILTER_ENUM_ARCH)/* && !installed*/) {
@@ -241,11 +240,10 @@
component = str.substr(0, found);
}

- if (pk_bitfield_contain(filters, PK_FILTER_ENUM_NOT_INSTALLED) && installed) {
+ if (pk_bitfield_contain(filters, PK_FILTER_ENUM_NOT_INSTALLED) && installed)
return false;
- } else if (pk_bitfield_contain(filters, PK_FILTER_ENUM_INSTALLED) && !installed) {
+ else if (pk_bitfield_contain(filters, PK_FILTER_ENUM_INSTALLED) && !installed)
return false;
- }

if (pk_bitfield_contain(filters, PK_FILTER_ENUM_DEVELOPMENT)) {
// if ver.end() means unknow
@@ -342,75 +340,72 @@

PkgList AptIntf::filterPackages(const PkgList &packages, PkBitfield filters)
{
- if (filters != 0) {
- PkgList ret;
- ret.reserve(packages.size());
+ if (filters == 0)
+ return packages;

- for (const pkgCache::VerIterator &ver : packages) {
- if (matchPackage(ver, filters)) {
- ret.push_back(ver);
- }
+ PkgList ret;
+ ret.reserve(packages.size());
+
+ for (const PkgInfo &info : packages) {
+ if (matchPackage(info.ver, filters)) {
+ ret.push_back(info);
}
+ }

- // This filter is more complex so we filter it after the list has shrunk
- if (pk_bitfield_contain(filters, PK_FILTER_ENUM_DOWNLOADED) && ret.size() > 0) {
- PkgList downloaded;
-
- pkgProblemResolver Fix(*m_cache);
- {
- pkgDepCache::ActionGroup group(*m_cache);
- for (auto autoInst : { true, false }) {
- for (const pkgCache::VerIterator &ver : ret) {
- if (m_cancel) {
- break;
- }
+ // This filter is more complex so we filter it after the list has shrunk
+ if (pk_bitfield_contain(filters, PK_FILTER_ENUM_DOWNLOADED) && ret.size() > 0) {
+ PkgList downloaded;

- m_cache->tryToInstall(Fix, ver, false, autoInst, false);
- }
+ pkgProblemResolver Fix(*m_cache);
+ {
+ pkgDepCache::ActionGroup group(*m_cache);
+ for (auto autoInst : { true, false }) {
+ for (const PkgInfo &pki : ret) {
+ if (m_cancel)
+ break;
+
+ m_cache->tryToInstall(Fix, pki, false, autoInst, false);
}
}
+ }

- // get a fetcher
- pkgAcquire fetcher;
+ // get a fetcher
+ pkgAcquire fetcher;

- // Read the source list
- if (m_cache->BuildSourceList() == false) {
- return downloaded;
- }
+ // Read the source list
+ if (m_cache->BuildSourceList() == false) {
+ return downloaded;
+ }

- // Create the package manager and prepare to download
- std::unique_ptr<pkgPackageManager> PM (_system->CreatePM(*m_cache));
- if (!PM->GetArchives(&fetcher, m_cache->GetSourceList(), m_cache->GetPkgRecords()) ||
- _error->PendingError() == true) {
- return downloaded;
- }
+ // Create the package manager and prepare to download
+ std::unique_ptr<pkgPackageManager> PM (_system->CreatePM(*m_cache));
+ if (!PM->GetArchives(&fetcher, m_cache->GetSourceList(), m_cache->GetPkgRecords()) ||
+ _error->PendingError() == true) {
+ return downloaded;
+ }

- for (const pkgCache::VerIterator &verIt : ret) {
- bool found = false;
- for (pkgAcquire::ItemIterator it = fetcher.ItemsBegin(); it < fetcher.ItemsEnd(); ++it) {
- pkgAcqArchiveSane *archive = static_cast<pkgAcqArchiveSane*>(dynamic_cast<pkgAcqArchive*>(*it));
- if (archive == nullptr) {
- continue;
- }
- const pkgCache::VerIterator ver = archive->version();
- if ((*it)->Local && verIt == ver) {
- found = true;
- break;
- }
+ for (const PkgInfo &info : ret) {
+ bool found = false;
+ for (pkgAcquire::ItemIterator it = fetcher.ItemsBegin(); it < fetcher.ItemsEnd(); ++it) {
+ pkgAcqArchiveSane *archive = static_cast<pkgAcqArchiveSane*>(dynamic_cast<pkgAcqArchive*>(*it));
+ if (archive == nullptr) {
+ continue;
}
-
- if (found) {
- downloaded.push_back(verIt);
+ const pkgCache::VerIterator ver = archive->version();
+ if ((*it)->Local && info.ver == ver) {
+ found = true;
+ break;
}
}

- return downloaded;
+ if (found)
+ downloaded.append(info);
}

- return ret;
- } else {
- return packages;
+ return downloaded;
}
+
+ return ret;
}

// used to emit packages it collects all the needed info
@@ -429,7 +424,7 @@
}

gchar *package_id;
- package_id = utilBuildPackageId(ver);
+ package_id = m_cache->buildPackageId(ver);
pk_backend_job_package(m_job,
state,
package_id,
@@ -440,7 +435,7 @@
void AptIntf::emitPackageProgress(const pkgCache::VerIterator &ver, PkStatusEnum status, uint percentage)
{
gchar *package_id;
- package_id = utilBuildPackageId(ver);
+ package_id = m_cache->buildPackageId(ver);
pk_backend_job_set_item_progress(m_job, package_id, status, percentage);
g_free(package_id);
}
@@ -454,12 +449,11 @@
output.removeDuplicates();

output = filterPackages(output, filters);
- for (const pkgCache::VerIterator &verIt : output) {
- if (m_cancel) {
+ for (const PkgInfo &info : output) {
+ if (m_cancel)
break;
- }

- emitPackage(verIt, state);
+ emitPackage(info.ver, state);
}
}

@@ -471,11 +465,10 @@
// Remove the duplicated entries
output.removeDuplicates();

- for (const pkgCache::VerIterator &verIt : output) {
- gchar *package_id;
- package_id = utilBuildPackageId(verIt);
+ for (const PkgInfo &info : output) {
+ g_autofree gchar *package_id = nullptr;
+ package_id = m_cache->buildPackageId(info.ver);
pk_backend_job_require_restart(m_job, PK_RESTART_ENUM_SYSTEM, package_id);
- g_free(package_id);
}
}

@@ -489,7 +482,7 @@
output.removeDuplicates();

output = filterPackages(output, filters);
- for (const pkgCache::VerIterator &verIt : output) {
+ for (const PkgInfo &pkgInfo : output) {
if (m_cancel) {
break;
}
@@ -498,7 +491,7 @@
state = PK_INFO_ENUM_NORMAL;

// let find what kind of upgrade this is
- pkgCache::VerFileIterator vf = verIt.FileList();
+ pkgCache::VerFileIterator vf = pkgInfo.ver.FileList();
std::string origin = vf.File().Origin() == NULL ? "" : vf.File().Origin();
std::string archive = vf.File().Archive() == NULL ? "" : vf.File().Archive();
std::string label = vf.File().Label() == NULL ? "" : vf.File().Label();
@@ -517,7 +510,7 @@
state = PK_INFO_ENUM_ENHANCEMENT;
}

- emitPackage(verIt, state);
+ emitPackage(pkgInfo.ver, state);
}
}

@@ -564,7 +557,7 @@
rec.GetRec(start, stop);
string record(start, stop - start);
if (matcher.matches(record, arch)) {
- output.push_back(ver);
+ output.append(ver);
}
}
}
@@ -632,7 +625,7 @@
std::transform(libPkgName.begin(), libPkgName.end(), libPkgName.begin(), ::tolower);

if (g_strcmp0 (pkg.Name (), libPkgName.c_str ()) == 0) {
- output.push_back(ver);
+ output.append(ver);
}
}
} else {
@@ -756,7 +749,7 @@
}

gchar *package_id;
- package_id = utilBuildPackageId(ver);
+ package_id = m_cache->buildPackageId(ver);
pk_backend_job_details(m_job,
package_id,
m_cache->getShortDescription(ver).c_str(),
@@ -777,12 +770,11 @@
// Remove the duplicated entries
pkgs.removeDuplicates();

- for (const pkgCache::VerIterator &verIt : pkgs) {
- if (m_cancel) {
+ for (const PkgInfo &pkgInfo : pkgs) {
+ if (m_cancel)
break;
- }

- emitPackageDetail(verIt);
+ emitPackageDetail(pkgInfo.ver);
}
}

@@ -801,7 +793,7 @@
const pkgCache::VerIterator &currver = m_cache->findVer(pkg);

// Build a package_id from the current version
- gchar *current_package_id = utilBuildPackageId(currver);
+ gchar *current_package_id = m_cache->buildPackageId(currver);

pkgCache::VerFileIterator vf = candver.FileList();
string origin = vf.File().Origin() == NULL ? "" : vf.File().Origin();
@@ -846,7 +838,7 @@
// Build a package_id from the update version
string archive = vf.File().Archive() == NULL ? "" : vf.File().Archive();
gchar *package_id;
- package_id = utilBuildPackageId(candver);
+ package_id = m_cache->buildPackageId(candver);

PkUpdateStateEnum updateState = PK_UPDATE_STATE_ENUM_UNKNOWN;
if (archive.compare("stable") == 0) {
@@ -910,12 +902,10 @@

void AptIntf::emitUpdateDetails(const PkgList &pkgs)
{
- for (const pkgCache::VerIterator &verIt : pkgs) {
- if (m_cancel) {
+ for (const PkgInfo &pi : pkgs) {
+ if (m_cancel)
break;
- }
-
- emitUpdateDetail(verIt);
+ emitUpdateDetail(pi.ver);
}
}

@@ -937,11 +927,11 @@
} else if (dep->Type == pkgCache::Dep::Depends) {
if (recursive) {
if (!output.contains(dep.TargetPkg())) {
- output.push_back(ver);
+ output.append(ver);
getDepends(output, ver, recursive);
}
} else {
- output.push_back(ver);
+ output.append(ver);
}
}
dep++;
@@ -967,15 +957,15 @@
if (parentVer.end() == false) {
PkgList deps;
getDepends(deps, parentVer, false);
- for (const pkgCache::VerIterator &depVer : deps) {
- if (depVer == ver) {
+ for (const PkgInfo &depInfo : deps) {
+ if (depInfo.ver == ver) {
if (recursive) {
if (!output.contains(parentPkg)) {
- output.push_back(parentVer);
+ output.append(parentVer);
getRequires(output, parentVer, recursive);
}
} else {
- output.push_back(parentVer);
+ output.append(parentVer);
}
break;
}
@@ -1002,9 +992,8 @@

// Don't insert virtual packages as they don't have all kinds of info
const pkgCache::VerIterator &ver = m_cache->findVer(pkg);
- if (ver.end() == false) {
- output.push_back(ver);
- }
+ if (ver.end() == false)
+ output.append(ver);
}
return output;
}
@@ -1052,7 +1041,7 @@
continue;
}

- output.push_back(ver);
+ output.append(ver);
}
return output;
}
@@ -1099,7 +1088,7 @@
// Don't insert virtual packages instead add what it provides
for (PkGroupEnum group : groups) {
if (group == get_enum_group(section)) {
- output.push_back(ver);
+ output.append(ver);
break;
}
}
@@ -1143,7 +1132,7 @@
// Don't insert virtual packages instead add what it provides
const pkgCache::VerIterator &ver = m_cache->findVer(pkg);
if (ver.end() == false) {
- output.push_back(ver);
+ output.append(ver);
} else {
// iterate over the provides list
for (pkgCache::PrvIterator Prv = pkg.ProvidesList(); Prv.end() == false; ++Prv) {
@@ -1153,7 +1142,7 @@
if (ownerVer.end() == false) {
// we add the package now because we will need to
// remove duplicates later anyway
- output.push_back(ownerVer);
+ output.append(ownerVer);
}
}
}
@@ -1180,7 +1169,7 @@
if (matchesQueries(queries, pkg.Name()) ||
matchesQueries(queries, (*m_cache).getLongDescription(ver))) {
// The package matched
- output.push_back(ver);
+ output.append(ver);
}
} else if (matchesQueries(queries, pkg.Name())) {
// The package is virtual and MATCHED the name
@@ -1194,7 +1183,7 @@
if (ownerVer.end() == false) {
// we add the package now because we will need to
// remove duplicates later anyway
- output.push_back(ownerVer);
+ output.append(ownerVer);
}
}
}
@@ -1298,7 +1287,7 @@
if (ver.end()) {
continue;
}
- output.push_back(ver);
+ output.append(ver);
}

return output;
@@ -1325,24 +1314,24 @@
} else if (state.Upgrade() == true && state.NewInstall() == false) {
const pkgCache::VerIterator &ver = m_cache->findCandidateVer(pkg);
if (!ver.end()) {
- updates.push_back(ver);
+ updates.append(ver);
}
} else if (state.Downgrade() == true) {
const pkgCache::VerIterator &ver = m_cache->findCandidateVer(pkg);
if (!ver.end()) {
- downgrades.push_back(ver);
+ downgrades.append(ver);
}
} else if (state.Upgradable() == true &&
pkg->CurrentVer != 0 &&
state.Delete() == false) {
const pkgCache::VerIterator &ver = m_cache->findCandidateVer(pkg);
if (!ver.end()) {
- blocked.push_back(ver);
+ blocked.append(ver);
}
} else if (state.NewInstall()) {
const pkgCache::VerIterator &ver = m_cache->findCandidateVer(pkg);
if (!ver.end()) {
- installs.push_back(ver);
+ installs.append(ver);
}
} else if (state.Delete()) {
const pkgCache::VerIterator &ver = m_cache->findCandidateVer(pkg);
@@ -1363,15 +1352,12 @@
}
}

- if( is_obsoleted )
- {
+ if (is_obsoleted ) {
/* Obsoleted packages */
- obsoleted.push_back(ver);
- }
- else
- {
+ obsoleted.append(ver);
+ } else {
/* Removed packages */
- removals.push_back(ver);
+ removals.append(ver);
}
}
}
@@ -1423,7 +1409,7 @@
if (ver.end() == true)
continue;

- output.push_back(ver);
+ output.append(ver);
}

/* check if we found nothing because AppStream data is missing completely */
@@ -1588,7 +1574,7 @@
if (archive == nullptr) {
continue;
}
- untrusted.push_back(archive->version());
+ untrusted.append(archive->version());

UntrustedList += string((*I)->ShortDesc()) + " ";
}
@@ -1637,19 +1623,19 @@
// installing;
const pkgCache::VerIterator &ver = m_cache->findCandidateVer(pkg);
if (!ver.end()) {
- ret.push_back(ver);
- installing.push_back(ver);
+ ret.append(ver);
+ installing.append(ver);

// append to the restart required list
if (utilRestartRequired(pkg.Name())) {
- m_restartPackages.push_back(ver);
+ m_restartPackages.append(ver);
}
}
} else if ((*m_cache)[pkg].Delete() == true) {
// removing
const pkgCache::VerIterator &ver = m_cache->findVer(pkg);
if (!ver.end()) {
- ret.push_back(ver);
+ ret.append(ver);

bool is_obsoleted = false;

@@ -1668,38 +1654,37 @@
}

if (!is_obsoleted) {
- removing.push_back(ver);
+ removing.append(ver);
} else {
- obsoleting.push_back(ver);
+ obsoleting.append(ver);
}

// append to the restart required list
if (utilRestartRequired(pkg.Name())) {
- m_restartPackages.push_back(ver);
+ m_restartPackages.append(ver);
}
}
} else if ((*m_cache)[pkg].Upgrade() == true) {
// updating
const pkgCache::VerIterator &ver = m_cache->findCandidateVer(pkg);
if (!ver.end()) {
- ret.push_back(ver);
- updating.push_back(ver);
+ ret.append(ver);
+ updating.append(ver);

// append to the restart required list
- if (utilRestartRequired(pkg.Name())) {
- m_restartPackages.push_back(ver);
- }
+ if (utilRestartRequired(pkg.Name()))
+ m_restartPackages.append(ver);
}
} else if ((*m_cache)[pkg].Downgrade() == true) {
// downgrading
const pkgCache::VerIterator &ver = m_cache->findVer(pkg);
if (!ver.end()) {
- ret.push_back(ver);
- downgrading.push_back(ver);
+ ret.append(ver);
+ downgrading.append(ver);

// append to the restart required list
if (utilRestartRequired(pkg.Name())) {
- m_restartPackages.push_back(ver);
+ m_restartPackages.append(ver);
}
}
}
@@ -1719,9 +1704,9 @@

pkgCache::VerIterator AptIntf::findTransactionPackage(const std::string &name)
{
- for (const pkgCache::VerIterator &verIt : m_pkgs) {
- if (verIt.ParentPkg().Name() == name) {
- return verIt;
+ for (const PkgInfo &pkInfo : m_pkgs) {
+ if (pkInfo.ver.ParentPkg().Name() == name) {
+ return pkInfo.ver;
}
}

@@ -1767,16 +1752,15 @@
}
//cout << "got line: " << line << endl;

- gchar **split = g_strsplit(line, ":",5);
- gchar *status = g_strstrip(split[0]);
- gchar *pkg = g_strstrip(split[1]);
- gchar *percent = g_strstrip(split[2]);
- gchar *str = g_strdup(g_strstrip(split[3]));
+ g_auto(GStrv) split = g_strsplit(line, ":",5);
+ const gchar *status = g_strstrip(split[0]);
+ const gchar *pkg = g_strstrip(split[1]);
+ const gchar *percent = g_strstrip(split[2]);
+ g_autofree gchar *str = g_strdup(g_strstrip(split[3]));

// major problem here, we got unexpected input. should _never_ happen
- if(!(pkg && status)) {
+ if(pkg == nullptr && status == nullptr)
continue;
- }

// Since PackageKit doesn't emulate finished anymore
// we need to manually do it here, as at this point
@@ -2019,7 +2003,7 @@
// emitPackageProgress(ver, m_lastSubProgress);
}
} else {
- cout << ">>>Unmaped value<<< :" << line << endl;
+ std::cout << "aptcc: >>>Unmaped dpkg status value: " << line << std::endl;
}

if (!starts_with(str, "Running")) {
@@ -2035,8 +2019,6 @@
pk_backend_job_set_percentage(m_job, val);

// clean-up
- g_strfreev(split);
- g_free(str);
line[0] = 0;
} else {
buf[1] = 0;
@@ -2065,7 +2047,6 @@

PkgList AptIntf::resolvePackageIds(gchar **package_ids, PkBitfield filters)
{
- gchar *pi;
PkgList ret;

pk_backend_job_set_status (m_job, PK_STATUS_ENUM_QUERY);
@@ -2080,11 +2061,11 @@
break;
}

- pi = package_ids[i];
+ const gchar *pkgid = package_ids[i];

// Check if it's a valid package id
- if (pk_package_id_check(pi) == false) {
- string name(pi);
+ if (pk_package_id_check(pkgid) == false) {
+ string name(pkgid);
// Check if the package name didn't contains the arch field
if (name.find(':') == std::string::npos) {
// OK FindPkg is not suitable on muitarch without ":arch"
@@ -2108,15 +2089,13 @@

const pkgCache::VerIterator &ver = m_cache->findVer(pkg);
// check to see if the provided package isn't virtual too
- if (!ver.end()) {
- ret.push_back(ver);
- }
+ if (!ver.end())
+ ret.append(ver);

const pkgCache::VerIterator &candidateVer = m_cache->findCandidateVer(pkg);
// check to see if the provided package isn't virtual too
- if (!candidateVer.end()) {
- ret.push_back(candidateVer);
- }
+ if (!candidateVer.end())
+ ret.append(candidateVer);
}
} else {
const pkgCache::PkgIterator &pkg = (*m_cache)->FindPkg(name);
@@ -2127,22 +2106,19 @@

const pkgCache::VerIterator &ver = m_cache->findVer(pkg);
// check to see if the provided package isn't virtual too
- if (ver.end() == false) {
- ret.push_back(ver);
- }
+ if (ver.end() == false)
+ ret.append(ver);

const pkgCache::VerIterator &candidateVer = m_cache->findCandidateVer(pkg);
// check to see if the provided package isn't virtual too
- if (candidateVer.end() == false) {
- ret.push_back(candidateVer);
- }
+ if (candidateVer.end() == false)
+ ret.append(candidateVer);
}
} else {
- const pkgCache::VerIterator &ver = m_cache->resolvePkgID(pi);
+ const PkgInfo &pkgi = m_cache->resolvePkgID(pkgid);
// check to see if we found the package
- if (!ver.end()) {
- ret.push_back(ver);
- }
+ if (!pkgi.ver.end())
+ ret.append(pkgi);
}
}

@@ -2172,13 +2148,12 @@

void AptIntf::markAutoInstalled(const PkgList &pkgs)
{
- for (const pkgCache::VerIterator &verIt : pkgs) {
- if (m_cancel) {
+ for (const PkgInfo &pkInfo : pkgs) {
+ if (m_cancel)
break;
- }

// Mark package as auto-installed
- (*m_cache)->MarkAuto(verIt.ParentPkg(), true);
+ (*m_cache)->MarkAuto(pkInfo.ver.ParentPkg(), true);
}
}

@@ -2197,9 +2172,8 @@
}

// Set any version providing the .deb as the candidate.
- for (auto Prv = P.ProvidesList(); Prv.end() == false; Prv++) {
- ret.push_back(Prv.OwnerVer());
- }
+ for (auto Prv = P.ProvidesList(); Prv.end() == false; Prv++)
+ ret.append(Prv.OwnerVer());

// TODO do we need this?
// via cacheset to have our usual virtual handling
@@ -2236,7 +2210,7 @@
for (pkgCache::PkgIterator pkg = (*m_cache)->PkgBegin(); ! pkg.end(); ++pkg) {
const pkgCache::VerIterator &ver = pkg.CurrentVer();
if (!ver.end() && m_cache->isGarbage(pkg))
- initial_garbage.push_back(ver);
+ initial_garbage.append(ver);
}
}

@@ -2245,24 +2219,30 @@
pkgDepCache::ActionGroup group(*m_cache);

for (auto op : { Operation { install, false }, Operation { update, true } }) {
+ // We first need to mark all manual selections with AutoInst=false, so they influence which packages
+ // are chosen when resolving dependencies.
+ // Consider A depends X|Y, with installation of A,Y requested.
+ // With just one run and AutoInst=true, A would be marked for install, it would auto-install X;
+ // then Y is marked for install, and we end up with both X and Y marked for install.
+ // With two runs (one without AutoInst and one with AutoInst), we first mark A and Y for install.
+ // In the 2nd run, when resolving X|Y APT notices that X is already marked for install, and does not install Y.
for (auto autoInst : { false, true }) {
- for (const pkgCache::VerIterator &verIt : op.list) {
+ for (const PkgInfo &pkInfo : op.list) {
if (m_cancel) {
break;
}
- if (!m_cache->tryToInstall(Fix, verIt, BrokenFix, autoInst, op.preserveAuto)) {
+ if (!m_cache->tryToInstall(Fix, pkInfo, BrokenFix, autoInst, op.preserveAuto)) {
return false;
}
}
}
}

- for (const pkgCache::VerIterator &verIt : remove) {
- if (m_cancel) {
+ for (const PkgInfo &pkInfo : remove) {
+ if (m_cancel)
break;
- }

- m_cache->tryToRemove(Fix, verIt);
+ m_cache->tryToRemove(Fix, pkInfo);
}

// Call the scored problem resolver
@@ -2285,7 +2265,7 @@
for (pkgCache::PkgIterator pkg = (*m_cache)->PkgBegin(); ! pkg.end(); ++pkg) {
const pkgCache::VerIterator &ver = pkg.CurrentVer();
if (!ver.end() && !initial_garbage.contains(pkg) && m_cache->isGarbage(pkg))
- m_cache->tryToRemove (Fix, ver);
+ m_cache->tryToRemove (Fix, PkgInfo(ver));
}
}

@@ -2510,14 +2490,16 @@
if ((m_interactive) && (socket != NULL)) {
g_setenv("DEBIAN_FRONTEND", "passthrough", TRUE);
g_setenv("DEBCONF_PIPE", socket, TRUE);
+
+ // Set the LANGUAGE so debconf messages get localization
+ // NOTE: This will cause dpkg messages to be localized and APTcc's string matching
+ // to fail, so progress information may no longer be accurate in these cases.
+ setEnvLocaleFromJob();
} else {
// we don't have a socket set or are not interactive, let's fallback to noninteractive
g_setenv("DEBIAN_FRONTEND", "noninteractive", TRUE);
}

- // Set the LANGUAGE so debconf messages get localization
- setEnvLocaleFromJob();
-
// apt will record this in its history.log
guint uid = pk_backend_job_get_uid(m_job);
if (uid > 0) {
@@ -2544,7 +2526,8 @@
_exit(res);
}

- cout << "PARENT process running..." << endl;
+ cout << "APTcc parent process running..." << endl;
+
// make it nonblocking, verry important otherwise
// when the child finish we stay stuck.
fcntl(readFromChildFD[0], F_SETFL, O_NONBLOCK);
@@ -2559,7 +2542,7 @@
char masterbuf[1024];
while (waitpid(m_child_pid, &ret, WNOHANG) == 0) {
// TODO: This is dpkg's raw output. Maybe save it for error-solving?
- while(read(pty_master, masterbuf, sizeof(masterbuf)) > 0);
+ while (read(pty_master, masterbuf, sizeof(masterbuf)) > 0);
updateInterface(readFromChildFD[0], pty_master);
}

@@ -2568,6 +2551,6 @@
close(pty_master);
_system->LockInner();

- cout << "Parent finished..." << endl;
+ cout << "APTcc Parent finished..." << endl;
return true;
}
diff -Nru packagekit-1.2.4/backends/aptcc/apt-messages.cpp packagekit-1.2.4+git20220215/backends/aptcc/apt-messages.cpp
--- packagekit-1.2.4/backends/aptcc/apt-messages.cpp 2021-07-30 01:24:45.078523000 -0700
+++ packagekit-1.2.4+git20220215/backends/aptcc/apt-messages.cpp 2022-02-15 11:44:24.000000000 -0800
@@ -61,6 +61,6 @@
pk_backend_job_error_code(job,
errorCode,
"%s",
- utf8(errors.str().c_str()));
+ toUtf8(errors.str().c_str()));
}
}
diff -Nru packagekit-1.2.4/backends/aptcc/apt-utils.cpp packagekit-1.2.4+git20220215/backends/aptcc/apt-utils.cpp
--- packagekit-1.2.4/backends/aptcc/apt-utils.cpp 2021-07-30 01:24:45.078523000 -0700
+++ packagekit-1.2.4+git20220215/backends/aptcc/apt-utils.cpp 2022-02-15 11:44:24.000000000 -0800
@@ -1,7 +1,7 @@
/* apt-utils.cpp
*
* Copyright (c) 2009 Daniel Nicoletti <dantti12@gmail.com>
- * Copyright (c) 2014 Matthias Klumpp <mak@debian.org>
+ * Copyright (c) 2014-2022 Matthias Klumpp <mak@debian.org>
*
* 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
@@ -209,7 +209,7 @@
if (starts_with(line, " "))
line.erase(0,1);
// no need to free str later, it is allocated in a static buffer
- const char *str = utf8(line.c_str());
+ const char *str = toUtf8(line.c_str());
if (strcmp(str, "") == 0) {
changelog.append("\n");
continue;
@@ -383,9 +383,10 @@
bool utilRestartRequired(const string &packageName)
{
if (starts_with(packageName, "linux-image-") ||
- starts_with(packageName, "nvidia-") ||
- packageName == "libc6" ||
- packageName == "dbus") {
+ starts_with(packageName, "nvidia-") ||
+ packageName == "libc6" ||
+ packageName == "dbus" ||
+ packageName == "dbus-broker") {
return true;
}
return false;
@@ -393,11 +394,11 @@

string utilBuildPackageOriginId(pkgCache::VerFileIterator vf)
{
- if (vf.File().Origin() == NULL)
+ if (vf.File().Origin() == nullptr)
return string("local");
- if (vf.File().Archive() == NULL)
+ if (vf.File().Archive() == nullptr)
return string("local");
- if (vf.File().Component() == NULL)
+ if (vf.File().Component() == nullptr)
return string("invalid");

// https://wiki.debian.org/DebianRepository/Format
@@ -418,9 +419,9 @@
// Sanitize it!
// All space characters, control characters and punctuation get replaced
// with underscore.
- // In particular the punctuations ',' and ';' may be used as list separators
- // so we must not have them appear in our package_ids as that would break
- // any number of higher level features.
+ // In particular the punctuations ':', ';' and ',' may be used as list separators
+ // so we must not have them appear in our package_ids as that would cause
+ // breakage down the line.
std::transform(origin.begin(), origin.end(), origin.begin(), ::tolower);
origin = std::regex_replace(origin, std::regex("[[:space:][:cntrl:][:punct:]]+"), "_");

@@ -428,37 +429,14 @@
return res;
}

-gchar* utilBuildPackageId(const pkgCache::VerIterator &ver)
+const char *toUtf8(const char *str)
{
- gchar *package_id;
- pkgCache::VerFileIterator vf = ver.FileList();
-
- string data = "";
- const pkgCache::PkgIterator &pkg = ver.ParentPkg();
- if (pkg->CurrentState == pkgCache::State::Installed && pkg.CurrentVer() == ver) {
- // when a package is installed, the data part of a package-id is "installed:<repo-id>"
- data = "installed:" + utilBuildPackageOriginId(vf);
- } else {
- data = utilBuildPackageOriginId(vf);
- }
-
- package_id = pk_package_id_build(ver.ParentPkg().Name(),
- ver.VerStr(),
- ver.Arch(),
- data.c_str());
- return package_id;
-}
-
-const char *utf8(const char *str)
-{
- static char *_str = NULL;
- if (str == NULL) {
+ static __thread char *_str = NULL;
+ if (str == NULL)
return NULL;
- }

- if (g_utf8_validate(str, -1, NULL) == true) {
+ if (g_utf8_validate(str, -1, NULL) == true)
return str;
- }

g_free(_str);
_str = NULL;
diff -Nru packagekit-1.2.4/backends/aptcc/apt-utils.h packagekit-1.2.4+git20220215/backends/aptcc/apt-utils.h
--- packagekit-1.2.4/backends/aptcc/apt-utils.h 2021-07-30 01:24:45.078523000 -0700
+++ packagekit-1.2.4+git20220215/backends/aptcc/apt-utils.h 2022-02-15 11:44:24.000000000 -0800
@@ -72,12 +72,6 @@
bool utilRestartRequired(const string &packageName);

/**
- * Build a package id from the given package version
- * The caller must g_free the returned value
- */
-gchar* utilBuildPackageId(const pkgCache::VerIterator &ver);
-
-/**
* Build a unique repository origin, in the form of
* {distro}-{suite}-{component}
*/
@@ -86,6 +80,6 @@
/**
* Return an utf8 string
*/
-const char *utf8(const char *str);
+const char *toUtf8(const char *str);

#endif
diff -Nru packagekit-1.2.4/backends/aptcc/pk-backend-aptcc.cpp packagekit-1.2.4+git20220215/backends/aptcc/pk-backend-aptcc.cpp
--- packagekit-1.2.4/backends/aptcc/pk-backend-aptcc.cpp 2021-07-30 01:24:45.079522800 -0700
+++ packagekit-1.2.4+git20220215/backends/aptcc/pk-backend-aptcc.cpp 2022-02-15 11:44:24.000000000 -0800
@@ -214,8 +214,8 @@
return;
}

- const pkgCache::VerIterator &ver = apt->aptCacheFile()->resolvePkgID(pi);
- if (ver.end()) {
+ const PkgInfo &pkInfo = apt->aptCacheFile()->resolvePkgID(pi);
+ if (pkInfo.ver.end()) {
pk_backend_job_error_code(job,
PK_ERROR_ENUM_PACKAGE_NOT_FOUND,
"Couldn't find package %s",
@@ -224,9 +224,9 @@
}

if (role == PK_ROLE_ENUM_DEPENDS_ON) {
- apt->getDepends(output, ver, recursive);
+ apt->getDepends(output, pkInfo.ver, recursive);
} else {
- apt->getRequires(output, ver, recursive);
+ apt->getRequires(output, pkInfo.ver, recursive);
}
}

@@ -281,8 +281,8 @@
return;
}

- const pkgCache::VerIterator &ver = apt->aptCacheFile()->resolvePkgID(pi);
- if (ver.end()) {
+ const PkgInfo &pkInfo = apt->aptCacheFile()->resolvePkgID(pi);
+ if (pkInfo.ver.end()) {
pk_backend_job_error_code(job,
PK_ERROR_ENUM_PACKAGE_NOT_FOUND,
"Couldn't find package %s",
@@ -352,13 +352,12 @@

static void backend_get_files_local_thread(PkBackendJob *job, GVariant *params, gpointer user_data)
{
- gchar **files = nullptr;
+ g_autofree gchar **files = nullptr;
g_variant_get(params, "(^a&s)",
&files);
-
AptIntf *apt = static_cast<AptIntf*>(pk_backend_job_get_user_data(job));

- for (guint i = 0; i < g_strv_length(files); ++i)
+ for (guint i = 0; files[i] != nullptr; ++i)
apt->emitPackageFilesLocal(files[i]);
}

@@ -509,13 +508,13 @@
break;
}

- const pkgCache::VerIterator &ver = apt->aptCacheFile()->resolvePkgID(pi);
+ const PkgInfo &pkInfo = apt->aptCacheFile()->resolvePkgID(pi);
// Ignore packages that could not be found or that exist only due to dependencies.
- if (ver.end()) {
+ if (pkInfo.ver.end()) {
_error->Error("Can't find this package id \"%s\".", pi);
continue;
} else {
- if(!ver.Downloadable()) {
+ if(!pkInfo.ver.Downloadable()) {
_error->Error("No downloadable files for %s,"
"perhaps it is a local or obsolete" "package?",
pi);
@@ -524,7 +523,7 @@

string storeFileName;
if (!apt->getArchive(&fetcher,
- ver,
+ pkInfo.ver,
directory,
storeFileName)) {
return;
@@ -569,11 +568,11 @@
g_debug("Failed to create apt cache");
return;
}
-
+
PkBackend *backend = PK_BACKEND(pk_backend_job_get_backend(job));
if (pk_backend_is_online(backend)) {
apt->refreshCache();
-
+
if (_error->PendingError() == true) {
show_errors(job, PK_ERROR_ENUM_CANNOT_FETCH_SOURCES, true);
}
@@ -909,7 +908,7 @@
}

string sections = souceRecord->joinedSections();
-
+
string repoId = souceRecord->repoId();

if (role == PK_ROLE_ENUM_GET_REPO_LIST) {
diff -Nru packagekit-1.2.4/backends/aptcc/pkg-list.cpp packagekit-1.2.4+git20220215/backends/aptcc/pkg-list.cpp
--- packagekit-1.2.4/backends/aptcc/pkg-list.cpp 2021-07-30 01:24:45.079522800 -0700
+++ packagekit-1.2.4+git20220215/backends/aptcc/pkg-list.cpp 2022-02-15 11:44:24.000000000 -0800
@@ -1,6 +1,7 @@
/* pkg-list.cpp
*
* Copyright (c) 2012-2016 Daniel Nicoletti <dantti12@gmail.com>
+ * Copyright (c) 2015-2022 Matthias Klumpp <matthias@tenstral.net>
*
* 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
@@ -27,17 +28,19 @@
{
public:
compare() {}
-
- bool operator()(const pkgCache::VerIterator &a,
- const pkgCache::VerIterator &b) {
- int ret = strcmp(a.ParentPkg().Name(), b.ParentPkg().Name());
+
+ bool operator() (const PkgInfo &a, const PkgInfo &b)
+ {
+ const pkgCache::VerIterator &viA = a.ver;
+ const pkgCache::VerIterator &viB = b.ver;
+ int ret = strcmp(viA.ParentPkg().Name(), viB.ParentPkg().Name());
if (ret == 0) {
- ret = strcmp(a.VerStr(), b.VerStr());
+ ret = strcmp(viA.VerStr(), viB.VerStr());
if (ret == 0) {
- ret = strcmp(a.Arch(), b.Arch());
+ ret = strcmp(viA.Arch(), viB.Arch());
if (ret == 0) {
- pkgCache::VerFileIterator aVF = a.FileList();
- pkgCache::VerFileIterator bVF = b.FileList();
+ pkgCache::VerFileIterator aVF = viA.FileList();
+ pkgCache::VerFileIterator bVF = viB.FileList();
ret = strcmp(aVF.File().Archive() == NULL ? "" : aVF.File().Archive(),
bVF.File().Archive() == NULL ? "" : bVF.File().Archive());
}
@@ -52,15 +55,19 @@
{
public:
result_equality() {}
-
- bool operator() (const pkgCache::VerIterator &a, const pkgCache::VerIterator &b) {
+
+ bool operator() (const PkgInfo &a, const PkgInfo &b)
+ {
+ const pkgCache::VerIterator &viA = a.ver;
+ const pkgCache::VerIterator &viB = b.ver;
+
bool ret;
- ret = strcmp(a.ParentPkg().Name(), b.ParentPkg().Name()) == 0 &&
- strcmp(a.VerStr(), b.VerStr()) == 0 &&
- strcmp(a.Arch(), b.Arch()) == 0;
+ ret = strcmp(viA.ParentPkg().Name(), viB.ParentPkg().Name()) == 0 &&
+ strcmp(viA.VerStr(), viB.VerStr()) == 0 &&
+ strcmp(viA.Arch(), viB.Arch()) == 0;
if (ret) {
- pkgCache::VerFileIterator aVF = a.FileList();
- pkgCache::VerFileIterator bVF = b.FileList();
+ pkgCache::VerFileIterator aVF = viA.FileList();
+ pkgCache::VerFileIterator bVF = viB.FileList();
ret = strcmp(aVF.File().Archive() == NULL ? "" : aVF.File().Archive(),
bVF.File().Archive() == NULL ? "" : bVF.File().Archive()) == 0;
}
@@ -68,10 +75,15 @@
}
};

+void PkgList::append(const pkgCache::VerIterator &verIter, PkgAction action)
+{
+ this->push_back(PkgInfo(verIter, action));
+}
+
bool PkgList::contains(const pkgCache::PkgIterator &pkg)
{
- for (const pkgCache::VerIterator &ver : *this) {
- if (ver.ParentPkg() == pkg) {
+ for (const PkgInfo &info : *this) {
+ if (info.ver.ParentPkg() == pkg) {
return true;
}
}
diff -Nru packagekit-1.2.4/backends/aptcc/pkg-list.h packagekit-1.2.4+git20220215/backends/aptcc/pkg-list.h
--- packagekit-1.2.4/backends/aptcc/pkg-list.h 2021-07-30 01:24:45.079522800 -0700
+++ packagekit-1.2.4+git20220215/backends/aptcc/pkg-list.h 2022-02-15 11:44:24.000000000 -0800
@@ -1,6 +1,7 @@
/* pkg-list.h
*
- * Copyright (c) 2012 Daniel Nicoletti <dantti12@gmail.com>
+ * Copyright (c) 2012-2016 Daniel Nicoletti <dantti12@gmail.com>
+ * Copyright (c) 2015-2022 Matthias Klumpp <matthias@tenstral.net>
*
* 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
@@ -27,12 +28,49 @@
using std::vector;

/**
+ * A designated action to perform on a package.
+ */
+enum class PkgAction
+{
+ NONE,
+ INSTALL_AUTO,
+ INSTALL_MANUAL
+};
+
+/**
+ * Information about a package, mainly containing its VerIterator
+ * and some information about the intended action on a package
+ * extracted from a PackageKit package-ID.
+ */
+class PkgInfo
+{
+public:
+ explicit PkgInfo(const pkgCache::VerIterator &verIter)
+ : ver(verIter),
+ action(PkgAction::NONE) {};
+ explicit PkgInfo(const pkgCache::VerIterator &verIter, PkgAction a)
+ : ver(verIter),
+ action(a) {};
+ pkgCache::VerIterator ver;
+ PkgAction action;
+};
+
+/**
* This class is meant to show Operation Progress using PackageKit
*/
-class PkgList : public vector<pkgCache::VerIterator>
+class PkgList : public vector<PkgInfo>
{
public:
/**
+ * Add a new package to the list
+ * @param verIter The pkgCache::VerIterator assoicated with this package.
+ * @param action An optional action that should be performed on this package in future.
+ */
+ void append(const pkgCache::VerIterator &verIter, PkgAction action = PkgAction::NONE);
+
+ void append(const PkgInfo &pi) { this->push_back(pi); };
+
+ /**
* Return if the given vector contain a package
*/
bool contains(const pkgCache::PkgIterator &pkg);
diff -Nru packagekit-1.2.4/backends/dnf/pk-backend-dnf.c packagekit-1.2.4+git20220215/backends/dnf/pk-backend-dnf.c
--- packagekit-1.2.4/backends/dnf/pk-backend-dnf.c 2021-07-30 01:24:45.080523000 -0700
+++ packagekit-1.2.4+git20220215/backends/dnf/pk-backend-dnf.c 2022-02-15 11:44:24.000000000 -0800
@@ -70,6 +70,12 @@
HyGoal goal;
} PkBackendDnfJobData;

+static GPtrArray * pk_backend_find_refresh_repos (PkBackendJob *job,
+ DnfState *state,
+ GPtrArray *repos,
+ gboolean force,
+ GError **error);
+
const gchar *
pk_backend_get_description (PkBackend *backend)
{
@@ -555,11 +561,13 @@
gboolean ret;
DnfState *state_local;
g_autoptr(GPtrArray) repos = NULL;
+ g_autoptr(GPtrArray) refresh_repos = NULL;

/* set state */
ret = dnf_state_set_steps (state, error,
2, /* load files */
- 98, /* add repos */
+ 1, /* count */
+ 97, /* add repos */
-1);
if (!ret)
return FALSE;
@@ -573,6 +581,20 @@
if (!dnf_state_done (state, error))
return FALSE;

+ /* Find out what repositories potentially will get downloaded - we might need to update
+ * the appstream data for these repositories. Note that there is a small chance that the
+ * repo metadata could expire between the call to dnf_repo_check() at this point, and
+ * the call to dnf_repo_check() inside dnf_sack_add_repos() - in this case we'll end up
+ * with stale appstream data until the next metadata refresh.
+ */
+ refresh_repos = pk_backend_find_refresh_repos (job,
+ state,
+ repos,
+ FALSE /* !force */,
+ error);
+ if (refresh_repos == NULL)
+ return FALSE;
+
/* add each repo */
state_local = dnf_state_get_child (state);
ret = dnf_sack_add_repos (sack,
@@ -584,6 +606,12 @@
if (!ret)
return FALSE;

+ for (guint i = 0; i < refresh_repos->len; i++) {
+ DnfRepo *repo = g_ptr_array_index (refresh_repos, i);
+ if (!dnf_utils_refresh_repo_appstream (repo, error))
+ return FALSE;
+ }
+
/* done */
if (!dnf_state_done (state, error))
return FALSE;
@@ -1055,11 +1083,11 @@
pkglist = dnf_utils_run_query_with_filters (job, sack, query, filters);
break;
case PK_ROLE_ENUM_SEARCH_DETAILS:
- hy_query_filter_in (query, HY_PKG_DESCRIPTION, HY_SUBSTR, (const gchar **) search);
+ hy_query_filter_in (query, HY_PKG_DESCRIPTION, HY_ICASE | HY_SUBSTR, (const gchar **) search);
pkglist = dnf_utils_run_query_with_filters (job, sack, query, filters);
break;
case PK_ROLE_ENUM_SEARCH_NAME:
- hy_query_filter_in (query, HY_PKG_NAME, HY_SUBSTR, (const gchar **) search);
+ hy_query_filter_in (query, HY_PKG_NAME, HY_ICASE | HY_SUBSTR, (const gchar **) search);
pkglist = dnf_utils_run_query_with_filters (job, sack, query, filters);
break;
case PK_ROLE_ENUM_WHAT_PROVIDES:
@@ -1655,49 +1683,22 @@
pk_backend_repo_list_changed (backend);
}

-static void
-pk_backend_refresh_cache_thread (PkBackendJob *job,
- GVariant *params,
- gpointer user_data)
+static GPtrArray *
+pk_backend_find_refresh_repos (PkBackendJob *job,
+ DnfState *state,
+ GPtrArray *repos,
+ gboolean force,
+ GError **error)
{
- PkBackendDnfJobData *job_data = pk_backend_job_get_user_data (job);
- PkBackend *backend = pk_backend_job_get_backend (job);
- DnfRepo *repo;
+ g_autoptr(GPtrArray) refresh_repos = NULL;
DnfState *state_local;
DnfState *state_loop;
- gboolean force;
- gboolean ret;
guint cnt = 0;
guint i;
- g_autoptr(DnfSack) sack = NULL;
- g_autoptr(GError) error = NULL;
- g_autoptr(GPtrArray) refresh_repos = NULL;
- g_autoptr(GPtrArray) repos = NULL;
-
- /* set state */
- dnf_state_set_steps (job_data->state, NULL,
- 1, /* count */
- 95, /* download */
- 4, /* rebuild SAT */
- -1);
-
- g_variant_get (params, "(b)", &force);
-
- /* kick subscription-manager if it exists */
- pk_backend_refresh_subman (job);
-
- /* ask the context's repo loader for new repos, forcing it to reload them */
- repos = dnf_repo_loader_get_repos (dnf_context_get_repo_loader (job_data->context), &error);
- if (repos == NULL) {
- pk_backend_job_error_code (job,
- error->code,
- "failed to load repos: %s", error->message);
- return;
- }

/* count the enabled repos */
for (i = 0; i < repos->len; i++) {
- repo = g_ptr_array_index (repos, i);
+ DnfRepo *repo = g_ptr_array_index (repos, i);
if (dnf_repo_get_enabled (repo) == DNF_REPO_ENABLED_NONE)
continue;
if (dnf_repo_get_kind (repo) == DNF_REPO_KIND_MEDIA)
@@ -1709,12 +1710,12 @@

/* figure out which repos need refreshing */
refresh_repos = g_ptr_array_new ();
- state_local = dnf_state_get_child (job_data->state);
+ state_local = dnf_state_get_child (state);
dnf_state_set_number_steps (state_local, cnt);
for (i = 0; i < repos->len; i++) {
+ DnfRepo *repo = g_ptr_array_index (repos, i);
gboolean repo_okay;

- repo = g_ptr_array_index (repos, i);
if (dnf_repo_get_enabled (repo) == DNF_REPO_ENABLED_NONE)
continue;
if (dnf_repo_get_kind (repo) == DNF_REPO_KIND_MEDIA)
@@ -1733,16 +1734,59 @@
g_ptr_array_index (repos, i));

/* done */
- ret = dnf_state_done (state_local, &error);
- if (!ret) {
- pk_backend_job_error_code (job, error->code, "%s", error->message);
- return;
- }
+ if (!dnf_state_done (state_local, error))
+ return NULL;
}

/* done */
- ret = dnf_state_done (job_data->state, &error);
- if (!ret) {
+ if (!dnf_state_done (state, error))
+ return NULL;
+
+ return g_steal_pointer (&refresh_repos);
+}
+
+static void
+pk_backend_refresh_cache_thread (PkBackendJob *job,
+ GVariant *params,
+ gpointer user_data)
+{
+ PkBackendDnfJobData *job_data = pk_backend_job_get_user_data (job);
+ PkBackend *backend = pk_backend_job_get_backend (job);
+ DnfRepo *repo;
+ DnfState *state_local;
+ DnfState *state_loop;
+ gboolean force;
+ gboolean ret;
+ guint i;
+ g_autoptr(DnfSack) sack = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) refresh_repos = NULL;
+ g_autoptr(GPtrArray) repos = NULL;
+
+ /* set state */
+ dnf_state_set_steps (job_data->state, NULL,
+ 1, /* count */
+ 95, /* download */
+ 4, /* rebuild SAT */
+ -1);
+
+ g_variant_get (params, "(b)", &force);
+
+ /* kick subscription-manager if it exists */
+ pk_backend_refresh_subman (job);
+
+ /* ask the context's repo loader for new repos, forcing it to reload them */
+ repos = dnf_repo_loader_get_repos (dnf_context_get_repo_loader (job_data->context), &error);
+ if (repos == NULL) {
+ pk_backend_job_error_code (job,
+ error->code,
+ "failed to load repos: %s", error->message);
+ return;
+ }
+
+ /* figure out which repos need refreshing */
+ refresh_repos = pk_backend_find_refresh_repos (job, job_data->state, repos, force, &error);
+ if (refresh_repos == NULL) {
pk_backend_job_error_code (job, error->code, "%s", error->message);
return;
}
@@ -2912,7 +2956,6 @@
/**
* pk_backend_remove_packages_thread:
*
- * FIXME: Use autoremove
* FIXME: Use allow_deps
*/
static void
@@ -2950,12 +2993,6 @@
g_assert (ret);

/* not supported */
- if (autoremove) {
- pk_backend_job_error_code (job,
- PK_ERROR_ENUM_NOT_SUPPORTED,
- "autoremove is not supported");
- return;
- }
if (!allow_deps) {
pk_backend_job_error_code (job,
PK_ERROR_ENUM_NOT_SUPPORTED,
@@ -3028,7 +3065,11 @@
"Failed to find %s", package_ids[i]);
return;
}
- hy_goal_erase (job_data->goal, pkg);
+ if (autoremove) {
+ hy_goal_erase_flags (job_data->goal, pkg, HY_CLEAN_DEPS);
+ } else {
+ hy_goal_erase (job_data->goal, pkg);
+ }
}

/* run transaction */
diff -Nru packagekit-1.2.4/backends/nix/buildenv.nix.gen.hh packagekit-1.2.4+git20220215/backends/nix/buildenv.nix.gen.hh
--- packagekit-1.2.4/backends/nix/buildenv.nix.gen.hh 1969-12-31 16:00:00.000000000 -0800
+++ packagekit-1.2.4+git20220215/backends/nix/buildenv.nix.gen.hh 2022-02-15 11:44:24.000000000 -0800
@@ -0,0 +1,27 @@
+R"foo(
+{ derivations, manifest }:
+
+derivation {
+ name = "user-environment";
+ system = "builtin";
+ builder = "builtin:buildenv";
+
+ inherit manifest;
+
+ # !!! grmbl, need structured data for passing this in a clean way.
+ derivations =
+ map (d:
+ [ (d.meta.active or "true")
+ (d.meta.priority or 5)
+ (builtins.length d.outputs)
+ ] ++ map (output: builtins.getAttr output d) d.outputs)
+ derivations;
+
+ # Building user environments remotely just causes huge amounts of
+ # network traffic, so don't do that.
+ preferLocalBuild = true;
+
+ # Also don't bother substituting.
+ allowSubstitutes = false;
+}
+)foo"
diff -Nru packagekit-1.2.4/backends/nix/meson.build packagekit-1.2.4+git20220215/backends/nix/meson.build
--- packagekit-1.2.4/backends/nix/meson.build 2021-07-30 01:24:45.081523000 -0700
+++ packagekit-1.2.4+git20220215/backends/nix/meson.build 2022-02-15 11:44:24.000000000 -0800
@@ -1,23 +1,24 @@
add_languages('cpp')

-nix_expr_dep = dependency('nix-expr', version: '>=1.12')
-nix_main_dep = dependency('nix-main', version: '>=1.12')
-nix_store_dep = dependency('nix-store', version: '>=1.12')
+nix_expr_dep = dependency('nix-expr', version: '>=2.6')
+nix_main_dep = dependency('nix-main', version: '>=2.6')
+nix_store_dep = dependency('nix-store', version: '>=2.6')
+nix_cmd_dep = dependency('nix-cmd', version: '>=2.6')

shared_module(
'pk_backend_nix',
'pk-backend-nix.cc',
- 'nix-helpers.cc',
'nix-lib-plus.cc',
include_directories: packagekit_src_include,
dependencies: [
packagekit_glib2_dep,
nix_expr_dep,
nix_main_dep,
+ nix_cmd_dep,
nix_store_dep,
gmodule_dep,
],
- c_args: [
+ cpp_args: [
'-DPK_COMPILATION=1',
'-DG_LOG_DOMAIN="PackageKit-Nix"',
],
diff -Nru packagekit-1.2.4/backends/nix/nix-helpers.cc packagekit-1.2.4+git20220215/backends/nix/nix-helpers.cc
--- packagekit-1.2.4/backends/nix/nix-helpers.cc 2021-07-30 01:24:45.081523000 -0700
+++ packagekit-1.2.4+git20220215/backends/nix/nix-helpers.cc 1969-12-31 16:00:00.000000000 -0800
@@ -1,182 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tab-modes: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2016 Matthew Bauer <mjbauer95@gmail.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 i3n 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 "nix-helpers.hh"
-
-// find drv based on attrpath and system
-DrvInfo
-nix_find_drv (EvalState & state, DrvInfos drvs, gchar* package_id)
-{
- gchar** package_id_parts = pk_package_id_split (package_id);
-
- // string name (package_id_parts[0]);
- // string version (package_id_parts[1]);
- string system (package_id_parts[2]);
- string attrPath (package_id_parts[3]);
-
- for (auto drv : drvs)
- if (drv.attrPath == attrPath && drv.querySystem() == system)
- return drv;
-
- DrvInfo drv (state);
- return drv;
-}
-
-// generate package id from derivation
-gchar*
-nix_drv_package_id (DrvInfo & drv)
-{
- DrvName name (drv.queryName());
-
- return pk_package_id_build (
- name.name.c_str (),
- name.version.c_str (),
- drv.querySystem().c_str (),
- drv.attrPath.c_str ()
- );
-}
-
-// get all drvs from list of ids
-DrvInfos
-nix_get_drvs_from_ids (EvalState & state, DrvInfos drvs, gchar** package_ids)
-{
- DrvInfos _drvs;
-
- for (; *package_ids != NULL; package_ids++)
- _drvs.push_back (
- nix_find_drv (
- state,
- drvs,
- *package_ids
- )
- );
-
- return _drvs;
-}
-
-// return false if drvinfo doesn't conflicts with a filter
-bool
-nix_filter_drv (EvalState & state, DrvInfo & drv, const Settings & settings, PkBitfield filters)
-{
- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_VISIBLE) || pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_VISIBLE))
- if (!drv.hasFailed ())
- {
- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_VISIBLE))
- return FALSE;
- }
- else
- {
- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_VISIBLE))
- return FALSE;
- }
-
- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_ARCH) || pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_ARCH))
- if (drv.querySystem() == settings.thisSystem)
- {
- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_ARCH))
- return FALSE;
- }
- else
- {
- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_ARCH))
- return FALSE;
- }
-
- return TRUE;
-}
-
-// get current state
-EvalState*
-nix_get_state ()
-{
- auto store = openStore ();
- Strings searchPath;
- return new EvalState (searchPath, store);
-}
-
-// get all derivations
-// TODO: figure out how to speed this up
-DrvInfos
-nix_get_all_derivations (EvalState & state, const Path & homedir)
-{
- Value v;
- loadSourceExpr (state, homedir + "/.nix-defexpr", v);
-
- Bindings & bindings(*state.allocBindings(0));
-
- DrvInfos drvs;
- getDerivations (state, v, "", bindings, drvs, true);
-
- return drvs;
-}
-
-// get current nix profile frmo job's uid
-Path
-nix_get_profile (PkBackendJob* job)
-{
- guint uid = pk_backend_job_get_uid (job);
-
- struct passwd* uid_ent = NULL;
- if ((uid_ent = getpwuid (uid)) == NULL)
- g_error ("Failed to get HOME");
-
- string homedir (uid_ent->pw_dir);
-
- return homedir + "/.nix-profile";
-}
-
-// run func in a thread
-void
-pk_nix_run (PkBackendJob *job, PkStatusEnum status, PkBackendJobThreadFunc func, gpointer data)
-{
- g_return_if_fail (func != NULL);
-
- pk_backend_job_set_percentage (job, 0);
- pk_backend_job_set_allow_cancel (job, TRUE);
- pk_backend_job_set_status (job, status);
- pk_backend_job_set_started (job, TRUE);
-
- pk_backend_job_thread_create (job, func, data, NULL);
-}
-
-// emit an error if error not NULL
-void
-pk_nix_error_emit (PkBackendJob* job, GError* error)
-{
- PkErrorEnum code = PK_ERROR_ENUM_UNKNOWN;
- g_return_if_fail (error != NULL);
- pk_backend_job_error_code (job, code, "%s", error->message);
-}
-
-// finish running job
-gboolean
-pk_nix_finish (PkBackendJob* job, GError* error)
-{
- if (error != NULL) {
- pk_nix_error_emit (job, error);
- return FALSE;
- }
-
- pk_backend_job_set_percentage (job, 100);
- pk_backend_job_finished (job);
-
- return TRUE;
-}
diff -Nru packagekit-1.2.4/backends/nix/nix-helpers.hh packagekit-1.2.4+git20220215/backends/nix/nix-helpers.hh
--- packagekit-1.2.4/backends/nix/nix-helpers.hh 2021-07-30 01:24:45.081523000 -0700
+++ packagekit-1.2.4+git20220215/backends/nix/nix-helpers.hh 1969-12-31 16:00:00.000000000 -0800
@@ -1,63 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tab-modes: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2016 Matthew Bauer <mjbauer95@gmail.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 i3n 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 NIX_HELPERS_HH
-#define NIX_HELPERS_HH
-
-#include <pwd.h>
-#include <glib.h>
-
-#include <pk-backend.h>
-#include <pk-backend-job.h>
-
-#include "nix-lib-plus.hh"
-
-void
-pk_nix_run (PkBackendJob *job, PkStatusEnum status, PkBackendJobThreadFunc func, gpointer data);
-
-void
-pk_nix_error_emit (PkBackendJob* job, GError* error);
-
-gboolean
-pk_nix_finish (PkBackendJob* job, GError* error);
-
-DrvInfos
-nix_get_drvs_from_ids (EvalState & state, DrvInfos drvs, gchar** package_ids);
-
-EvalState*
-nix_get_state ();
-
-DrvInfos
-nix_get_all_derivations (EvalState & state, const Path & path);
-
-gchar*
-nix_drv_package_id (DrvInfo & drv);
-
-DrvInfo
-nix_find_drv (EvalState & state, DrvInfos drvs, gchar* package_id);
-
-bool
-nix_filter_drv (EvalState & state, DrvInfo & drv, const Settings & settings, PkBitfield filters);
-
-Path
-nix_get_profile (PkBackendJob* job);
-
-#endif
diff -Nru packagekit-1.2.4/backends/nix/nix-lib-plus.cc packagekit-1.2.4+git20220215/backends/nix/nix-lib-plus.cc
--- packagekit-1.2.4/backends/nix/nix-lib-plus.cc 2021-07-30 01:24:45.081523000 -0700
+++ packagekit-1.2.4+git20220215/backends/nix/nix-lib-plus.cc 2022-02-15 11:44:24.000000000 -0800
@@ -11,11 +11,28 @@
For more information visit http://nixos.org/nix/
*/

+#include <nix/config.h>
+
+#include <nix/util.hh>
+#include <nix/derivations.hh>
+#include <nix/store-api.hh>
+#include <nix/path-with-outputs.hh>
+#include <nix/local-fs-store.hh>
+#include <nix/globals.hh>
+#include <nix/shared.hh>
+#include <nix/eval.hh>
+#include <nix/eval-inline.hh>
+#include <nix/profiles.hh>
+
#include "nix-lib-plus.hh"

+namespace nix {
+
DrvInfos queryInstalled(EvalState & state, const Path & userEnv)
{
DrvInfos elems;
+ if (pathExists(userEnv + "/manifest.json"))
+ throw Error("profile '%s' is incompatible with 'nix-env'; please use 'nix profile' instead", userEnv);
Path manifestFile = userEnv + "/manifest.nix";
if (pathExists(manifestFile)) {
Value v;
@@ -32,104 +49,113 @@
{
/* Build the components in the user environment, if they don't
exist already. */
- PathSet drvsToBuild;
+ std::vector<StorePathWithOutputs> drvsToBuild;
for (auto & i : elems)
if (i.queryDrvPath() != "")
- drvsToBuild.insert(i.queryDrvPath());
+ drvsToBuild.push_back({state.store->parseStorePath(i.queryDrvPath()), {}});

debug(format("building user environment dependencies"));
- state.store->buildPaths(drvsToBuild, state.repair ? bmRepair : bmNormal);
+ state.store->buildPaths(
+ toDerivedPaths(drvsToBuild),
+ state.repair ? bmRepair : bmNormal);

/* Construct the whole top level derivation. */
- PathSet references;
+ StorePathSet references;
Value manifest;
state.mkList(manifest, elems.size());
- unsigned int n = 0;
+ size_t n = 0;
for (auto & i : elems) {
/* Create a pseudo-derivation containing the name, system,
output paths, and optionally the derivation path, as well
as the meta attributes. */
Path drvPath = keepDerivations ? i.queryDrvPath() : "";
+ DrvInfo::Outputs outputs = i.queryOutputs(true);
+ StringSet metaNames = i.queryMetaNames();

- Value & v(*state.allocValue());
- manifest.listElems()[n++] = &v;
- state.mkAttrs(v, 16);
+ auto attrs = state.buildBindings(7 + outputs.size());

- mkString(*state.allocAttr(v, state.sType), "derivation");
- mkString(*state.allocAttr(v, state.sName), i.queryName());
+ attrs.alloc(state.sType).mkString("derivation");
+ attrs.alloc(state.sName).mkString(i.queryName());
auto system = i.querySystem();
if (!system.empty())
- mkString(*state.allocAttr(v, state.sSystem), system);
- mkString(*state.allocAttr(v, state.sOutPath), i.queryOutPath());
+ attrs.alloc(state.sSystem).mkString(system);
+ attrs.alloc(state.sOutPath).mkString(i.queryOutPath());
if (drvPath != "")
- mkString(*state.allocAttr(v, state.sDrvPath), i.queryDrvPath());
+ attrs.alloc(state.sDrvPath).mkString(i.queryDrvPath());

// Copy each output meant for installation.
- DrvInfo::Outputs outputs = i.queryOutputs(true);
- Value & vOutputs = *state.allocAttr(v, state.sOutputs);
+ auto & vOutputs = attrs.alloc(state.sOutputs);
state.mkList(vOutputs, outputs.size());
- unsigned int m = 0;
- for (auto & j : outputs) {
- mkString(*(vOutputs.listElems()[m++] = state.allocValue()), j.first);
- Value & vOutputs = *state.allocAttr(v, state.symbols.create(j.first));
- state.mkAttrs(vOutputs, 2);
- mkString(*state.allocAttr(vOutputs, state.sOutPath), j.second);
+ for (const auto & [m, j] : enumerate(outputs)) {
+ (vOutputs.listElems()[m] = state.allocValue())->mkString(j.first);
+ auto outputAttrs = state.buildBindings(2);
+ outputAttrs.alloc(state.sOutPath).mkString(j.second);
+ attrs.alloc(j.first).mkAttrs(outputAttrs);

/* This is only necessary when installing store paths, e.g.,
`nix-env -i /nix/store/abcd...-foo'. */
- state.store->addTempRoot(j.second);
- state.store->ensurePath(j.second);
+ state.store->addTempRoot(state.store->parseStorePath(j.second));
+ state.store->ensurePath(state.store->parseStorePath(j.second));

- references.insert(j.second);
+ references.insert(state.store->parseStorePath(j.second));
}

// Copy the meta attributes.
- Value & vMeta = *state.allocAttr(v, state.sMeta);
- state.mkAttrs(vMeta, 16);
- StringSet metaNames = i.queryMetaNames();
+ auto meta = state.buildBindings(metaNames.size());
for (auto & j : metaNames) {
Value * v = i.queryMeta(j);
if (!v) continue;
- vMeta.attrs->push_back(Attr(state.symbols.create(j), v));
+ meta.insert(state.symbols.create(j), v);
}
- vMeta.attrs->sort();
- v.attrs->sort();

- if (drvPath != "") references.insert(drvPath);
+ attrs.alloc(state.sMeta).mkAttrs(meta);
+
+ (manifest.listElems()[n++] = state.allocValue())->mkAttrs(attrs);
+
+ if (drvPath != "") references.insert(state.store->parseStorePath(drvPath));
}

/* Also write a copy of the list of user environment elements to
the store; we need it for future modifications of the
environment. */
- Path manifestFile = state.store->addTextToStore("env-manifest.nix",
- (format("%1%") % manifest).str(), references);
+ auto manifestFile = state.store->addTextToStore("env-manifest.nix",
+ fmt("%s", manifest), references);

/* Get the environment builder expression. */
Value envBuilder;
- state.evalFile(state.findFile("nix/buildenv.nix"), envBuilder);
+ state.eval(state.parseExprFromString(
+ #include "buildenv.nix.gen.hh"
+ , "/"), envBuilder);

/* Construct a Nix expression that calls the user environment
builder with the manifest as argument. */
- Value args, topLevel;
- state.mkAttrs(args, 3);
- mkString(*state.allocAttr(args, state.symbols.create("manifest")),
- manifestFile, {manifestFile});
- args.attrs->push_back(Attr(state.symbols.create("derivations"), &manifest));
- args.attrs->sort();
- mkApp(topLevel, envBuilder, args);
+ auto attrs = state.buildBindings(3);
+ attrs.alloc("manifest").mkString(
+ state.store->printStorePath(manifestFile),
+ {state.store->printStorePath(manifestFile)});
+ attrs.insert(state.symbols.create("derivations"), &manifest);
+ Value args;
+ args.mkAttrs(attrs);
+
+ Value topLevel;
+ topLevel.mkApp(&envBuilder, &args);

/* Evaluate it. */
debug("evaluating user environment builder");
state.forceValue(topLevel);
PathSet context;
Attr & aDrvPath(*topLevel.attrs->find(state.sDrvPath));
- Path topLevelDrv = state.coerceToPath(aDrvPath.pos ? *(aDrvPath.pos) : noPos, *(aDrvPath.value), context);
+ auto topLevelDrv = state.store->parseStorePath(state.coerceToPath(*aDrvPath.pos, *aDrvPath.value, context));
Attr & aOutPath(*topLevel.attrs->find(state.sOutPath));
- Path topLevelOut = state.coerceToPath(aOutPath.pos ? *(aOutPath.pos) : noPos, *(aOutPath.value), context);
+ Path topLevelOut = state.coerceToPath(*aOutPath.pos, *aOutPath.value, context);

/* Realise the resulting store expression. */
debug("building user environment");
- state.store->buildPaths({topLevelDrv}, state.repair ? bmRepair : bmNormal);
+ std::vector<StorePathWithOutputs> topLevelDrvs;
+ topLevelDrvs.push_back({topLevelDrv, {}});
+ state.store->buildPaths(
+ toDerivedPaths(topLevelDrvs),
+ state.repair ? bmRepair : bmNormal);

/* Switch the current user environment to the output path. */
auto store2 = state.store.dynamic_pointer_cast<LocalFSStore>();
@@ -140,131 +166,17 @@

Path lockTokenCur = optimisticLockProfile(profile);
if (lockToken != lockTokenCur) {
- printError(format("profile '%1%' changed while we were busy; restarting") % profile);
+ printInfo("profile '%1%' changed while we were busy; restarting", profile);
return false;
}

debug(format("switching to new user environment"));
- Path generation = createGeneration(ref<LocalFSStore>(store2), profile, topLevelOut);
+ Path generation = createGeneration(ref<LocalFSStore>(store2), profile,
+ store2->parseStorePath(topLevelOut));
switchLink(profile, generation);
}

return true;
}

-bool isNixExpr(const Path & path, struct stat & st)
-{
- return S_ISREG(st.st_mode) || (S_ISDIR(st.st_mode) && pathExists(path + "/default.nix"));
-}
-
-
-void getAllExprs(EvalState & state,
- const Path & path, StringSet & attrs, Value & v)
-{
- StringSet namesSorted;
- for (auto & i : readDirectory(path)) namesSorted.insert(i.name);
-
- for (auto & i : namesSorted) {
- /* Ignore the manifest.nix used by profiles. This is
- necessary to prevent it from showing up in channels (which
- are implemented using profiles). */
- if (i == "manifest.nix") continue;
-
- Path path2 = path + "/" + i;
-
- struct stat st;
- if (stat(path2.c_str(), &st) == -1)
- continue; // ignore dangling symlinks in ~/.nix-defexpr
-
- if (isNixExpr(path2, st) && (!S_ISREG(st.st_mode) || hasSuffix(path2, ".nix"))) {
- /* Strip off the `.nix' filename suffix (if applicable),
- otherwise the attribute cannot be selected with the
- `-A' option. Useful if you want to stick a Nix
- expression directly in ~/.nix-defexpr. */
- string attrName = i;
- if (hasSuffix(attrName, ".nix"))
- attrName = string(attrName, 0, attrName.size() - 4);
- if (attrs.find(attrName) != attrs.end()) {
- printError(format("warning: name collision in input Nix expressions, skipping '%1%'") % path2);
- continue;
- }
- attrs.insert(attrName);
- /* Load the expression on demand. */
- Value & vFun = state.getBuiltin("import");
- Value & vArg(*state.allocValue());
- mkString(vArg, path2);
- if (v.attrs->size() == v.attrs->capacity())
- throw Error(format("too many Nix expressions in directory '%1%'") % path);
- mkApp(*state.allocAttr(v, state.symbols.create(attrName)), vFun, vArg);
- }
- else if (S_ISDIR(st.st_mode))
- /* `path2' is a directory (with no default.nix in it);
- recurse into it. */
- getAllExprs(state, path2, attrs, v);
- }
-}
-
-void loadSourceExpr(EvalState & state, const Path & path, Value & v)
-{
- struct stat st;
- if (stat(path.c_str(), &st) == -1)
- throw SysError(format("getting information about '%1%'") % path);
-
- if (isNixExpr(path, st)) {
- state.evalFile(path, v);
- return;
- }
-
- /* The path is a directory. Put the Nix expressions in the
- directory in a set, with the file name of each expression as
- the attribute name. Recurse into subdirectories (but keep the
- set flat, not nested, to make it easier for a user to have a
- ~/.nix-defexpr directory that includes some system-wide
- directory). */
- if (S_ISDIR(st.st_mode)) {
- state.mkAttrs(v, 1024);
- state.mkList(*state.allocAttr(v, state.symbols.create("_combineChannels")), 0);
- StringSet attrs;
- getAllExprs(state, path, attrs, v);
- v.attrs->sort();
- }
-}
-
-
-static void loadDerivations(EvalState & state, Path nixExprPath,
- string systemFilter, Bindings & autoArgs,
- const string & pathPrefix, DrvInfos & elems)
-{
- Value vRoot;
- loadSourceExpr(state, nixExprPath, vRoot);
-
- Value & v(*findAlongAttrPath(state, pathPrefix, autoArgs, vRoot));
-
- getDerivations(state, v, pathPrefix, autoArgs, elems, true);
-
- /* Filter out all derivations not applicable to the current
- system. */
- for (DrvInfos::iterator i = elems.begin(), j; i != elems.end(); i = j) {
- j = i; j++;
- if (systemFilter != "*" && i->querySystem() != systemFilter)
- elems.erase(i);
- }
-}
-
-int
-getPriority (EvalState & state, DrvInfo & drv)
-{
- return drv.queryMetaInt ("priority", 0);
-}
-
-int
-comparePriorities (EvalState & state, DrvInfo & drv1, DrvInfo & drv2)
-{
- return getPriority (state, drv2) - getPriority (state, drv1);
-}
-
-bool
-keep (DrvInfo & drv)
-{
- return drv.queryMetaBool ("keep", false);
}
diff -Nru packagekit-1.2.4/backends/nix/nix-lib-plus.hh packagekit-1.2.4+git20220215/backends/nix/nix-lib-plus.hh
--- packagekit-1.2.4/backends/nix/nix-lib-plus.hh 2021-07-30 01:24:45.081523000 -0700
+++ packagekit-1.2.4+git20220215/backends/nix/nix-lib-plus.hh 2022-02-15 11:44:24.000000000 -0800
@@ -11,39 +11,14 @@
For more information visit http://nixos.org/nix/
*/

-#ifndef NIX_LIB_PLUS_HH
-#define NIX_LIB_PLUS_HH
+#pragma once

-#include <nix/config.h>
-
-#include <nix/nixexpr.hh>
-#include <nix/shared.hh>
-#include <nix/eval.hh>
-#include <nix/eval-inline.hh>
-#include <nix/derivations.hh>
-#include <nix/store-api.hh>
#include <nix/get-drvs.hh>
-#include <nix/names.hh>
-#include <nix/profiles.hh>
-#include <nix/globals.hh>
-#include <nix/attr-path.hh>
-
-using namespace nix;

-DrvInfos queryInstalled(EvalState & state, const Path & userEnv);
+namespace nix {

bool createUserEnv(EvalState & state, DrvInfos & elems, const Path & profile, bool keepDerivations, const string & lockToken);

-bool isNixExpr(const Path & path, const struct stat & st);
-
-void loadSourceExpr(EvalState & state, const Path & path, Value & v);
-
-void getAllExprs(EvalState & state, const Path & path, StringSet & strings, Value & v);
-
-int getPriority (EvalState & state, DrvInfo & drv);
-
-int comparePriorities (EvalState & state, DrvInfo & drv1, DrvInfo & drv2);
-
-bool keep (DrvInfo & drv);
+DrvInfos queryInstalled(EvalState & state, const Path & userEnv);

-#endif
+}
diff -Nru packagekit-1.2.4/backends/nix/pk-backend-nix.cc packagekit-1.2.4+git20220215/backends/nix/pk-backend-nix.cc
--- packagekit-1.2.4/backends/nix/pk-backend-nix.cc 2021-07-30 01:24:45.081523000 -0700
+++ packagekit-1.2.4+git20220215/backends/nix/pk-backend-nix.cc 2022-02-15 11:44:24.000000000 -0800
@@ -19,52 +19,55 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

-#include <string.h>
-#include <stdlib.h>
-#include <gio/gio.h>
+#include <pk-backend.h>
+#include <pk-backend-job.h>
+
+#include <nix/config.h>
+
+#include <nix/globals.hh>
+#include <nix/eval.hh>
+#include <nix/store-api.hh>
+#include <nix/names.hh>
+#include <nix/eval-cache.hh>
+#include <nix/attr-path.hh>
+#include <nix/profiles.hh>
+#include <nix/flake/flake.hh>
+#include <nix/experimental-features.hh>
+#include <nix/installables.hh>
+
+#include <pwd.h>

-#include "nix-helpers.hh"
#include "nix-lib-plus.hh"

typedef struct {
- Path roothome;
+ nix::ref<nix::EvalState> state;
+ std::string defaultFlake;
} PkBackendNixPrivate;
-
static PkBackendNixPrivate* priv;
-static EvalState* state;
-static DrvInfos drvs;

void
pk_backend_initialize (GKeyFile* conf, PkBackend* backend)
{
- g_debug ("backend initalize start");
-
priv = g_new0 (PkBackendNixPrivate, 1);

- struct passwd* uid_ent = NULL;
- if ((uid_ent = getpwuid (getuid ())) == NULL)
- g_error ("Failed to get HOME");
- priv->roothome = uid_ent->pw_dir;
+ nix::loadConfFile ();
+ nix::initGC ();

- verbosity = (Verbosity) -1;
+ nix::verbosity = nix::lvlWarn;
+ nix::settings.verboseBuild = false;
+ nix::settings.experimentalFeatures = {nix::ExperimentalFeature::Flakes};
+ nix::evalSettings.pureEval = true;

- try
- {
- initNix();
- initGC();
+ const nix::Strings searchPath;
+ priv->state = nix::ref<nix::EvalState> (std::make_shared<nix::EvalState>(searchPath, nix::openStore ()));

- state = nix_get_state();
- }
- catch (std::exception & e)
- {
- }
+ // this might be useful as a configuration setting in the future
+ priv->defaultFlake = "nixpkgs";
}

void
pk_backend_destroy (PkBackend* backend)
{
- drvs.empty ();
- g_free (state);
g_free (priv);
}

@@ -86,7 +89,6 @@
return "Matthew Bauer <mjbauer95@gmail.com>";
}

-// TODO
PkBitfield
pk_backend_get_groups (PkBackend* backend)
{
@@ -97,41 +99,10 @@
pk_backend_get_filters (PkBackend* backend)
{
return pk_bitfield_from_enums (
- PK_FILTER_ENUM_VISIBLE,
- PK_FILTER_ENUM_NOT_VISIBLE,
- PK_FILTER_ENUM_ARCH,
- PK_FILTER_ENUM_NOT_ARCH,
PK_FILTER_ENUM_SUPPORTED,
PK_FILTER_ENUM_NOT_SUPPORTED,
PK_FILTER_ENUM_INSTALLED,
PK_FILTER_ENUM_NOT_INSTALLED,
-
- /* TODO:
-
- - breaks with unfree packages
- PK_FILTER_ENUM_DOWNLOADED,
- PK_FILTER_ENUM_NOT_DOWNLOADED,
- PK_FILTER_ENUM_FREE,
- PK_FILTER_ENUM_NOT_FREE,
-
- - others
- PK_FILTER_ENUM_NONE,
- PK_FILTER_ENUM_DEVELOPMENT,
- PK_FILTER_ENUM_NOT_DEVELOPMENT,
- PK_FILTER_ENUM_GUI,
- PK_FILTER_ENUM_NOT_GUI,
- PK_FILTER_ENUM_BASENAME,
- PK_FILTER_ENUM_NOT_BASENAME,
- PK_FILTER_ENUM_NEWEST,
- PK_FILTER_ENUM_NOT_NEWEST,
- PK_FILTER_ENUM_SOURCE,
- PK_FILTER_ENUM_NOT_SOURCE,
- PK_FILTER_ENUM_COLLECTIONS,
- PK_FILTER_ENUM_NOT_COLLECTIONS,
- PK_FILTER_ENUM_APPLICATION,
- PK_FILTER_ENUM_NOT_APPLICATION,
- */
-
-1
);
}
@@ -141,48 +112,16 @@
{
return pk_bitfield_from_enums (
PK_ROLE_ENUM_CANCEL,
- PK_ROLE_ENUM_DOWNLOAD_PACKAGES,
PK_ROLE_ENUM_GET_DETAILS,
PK_ROLE_ENUM_GET_PACKAGES,
- PK_ROLE_ENUM_GET_UPDATES,
PK_ROLE_ENUM_INSTALL_PACKAGES,
PK_ROLE_ENUM_REFRESH_CACHE,
PK_ROLE_ENUM_REMOVE_PACKAGES,
PK_ROLE_ENUM_RESOLVE,
PK_ROLE_ENUM_SEARCH_DETAILS,
PK_ROLE_ENUM_SEARCH_NAME,
-
- /* TODO
- - need to use binary cache db
- PK_ROLE_ENUM_SEARCH_FILE,
- PK_ROLE_ENUM_GET_FILES_LOCAL,
- PK_ROLE_ENUM_GET_FILES,
-
- - need to get data from repos through nix-channel
- PK_ROLE_ENUM_REPO_ENABLE,
- PK_ROLE_ENUM_GET_REPO_LIST,
- PK_ROLE_ENUM_REPO_REMOVE,
- PK_ROLE_ENUM_REPO_SET_DATA,
-
- - need to integrate with nixos
- PK_ROLE_ENUM_REPAIR_SYSTEM,
- PK_ROLE_ENUM_UPGRADE_SYSTEM,
- PK_ROLE_ENUM_GET_DISTRO_UPGRADES,
-
- - etc.
- PK_ROLE_ENUM_DEPENDS_ON,
- PK_ROLE_ENUM_REQUIRED_BY,
- PK_ROLE_ENUM_INSTALL_FILES,
- PK_ROLE_ENUM_INSTALL_SIGNATURE,
- PK_ROLE_ENUM_SEARCH_GROUP,
- PK_ROLE_ENUM_WHAT_PROVIDES,
- PK_ROLE_ENUM_ACCEPT_EULA,
- PK_ROLE_ENUM_GET_CATEGORIES,
- PK_ROLE_ENUM_GET_OLD_TRANSACTIONS,
- PK_ROLE_ENUM_WHAT_PROVIDES,
- PK_ROLE_ENUM_GET_UPDATE_DETAIL,
- PK_ROLE_ENUM_GET_DETAILS_LOCAL,
- */
+ PK_ROLE_ENUM_UPDATE_PACKAGES,
+ PK_ROLE_ENUM_GET_UPDATES,
-1
);
}
@@ -194,695 +133,590 @@
return g_strdupv ((gchar **) mime_types);
}

+static std::shared_ptr<nix::eval_cache::AttrCursor>
+nix_get_cursor (nix::EvalState & state, std::string flake, std::string attrPath)
+{
+ nix::flake::LockFlags lockFlags;
+ auto lockedFlake = std::make_shared<nix::flake::LockedFlake> (nix::flake::lockFlake (state, nix::parseFlakeRef(flake), lockFlags));
+
+ auto evalCache = nix::openEvalCache (state, lockedFlake);
+
+ return evalCache->getRoot()->findAlongAttrPath (nix::parseAttrPath (state, attrPath));
+}
+
static void
pk_backend_get_details_thread (PkBackendJob* job, GVariant* params, gpointer p)
{
- g_autoptr (GError) error = NULL;
-
- try
- {
- // possibly slow call
- if (drvs.empty ())
- drvs = nix_get_all_derivations (*state, priv->roothome);
-
- DrvInfos _drvs = nix_get_drvs_from_ids (*state, drvs, (gchar**) p);
-
- for (auto drv : _drvs)
- {
- if (pk_backend_job_is_cancelled (job))
- break;
+ gchar** package_ids;
+ g_variant_get (params, "(^a&s)", &package_ids);

- string license = "unknown";
- auto licenseMeta = drv.queryMeta ("license");
- if (licenseMeta != NULL && licenseMeta->type == tAttrs)
- {
- auto symbol = state->symbols.create ("fullName");
- Bindings::iterator fullName = licenseMeta->attrs->find (symbol);
- if (fullName != licenseMeta->attrs->end () && fullName->value->type == tString)
- license = fullName->value->string.s;
+ gchar** parts;
+ for (size_t i = 0; package_ids[i] != NULL; i++) {
+ // we put the attr path in "PK_PACKAGE_ID_NAME" because that's how we identify it
+ parts = pk_package_id_split (package_ids[i]);
+ std::string attrPath = std::string (parts[PK_PACKAGE_ID_NAME]);
+ std::string flake = std::string (parts[PK_PACKAGE_ID_DATA]);
+ g_strfreev (parts);
+
+ auto cursor = nix_get_cursor (*priv->state, flake, "legacyPackages." + nix::settings.thisSystem.get () + "." + attrPath);
+
+ if (pk_backend_job_is_cancelled (job))
+ return;
+
+ if (cursor && cursor->isDerivation ()) {
+ auto aMeta = cursor->maybeGetAttr ("meta");
+
+ auto aDescription = aMeta ? aMeta->maybeGetAttr ("description") : NULL;
+ std::string description = aDescription ? aDescription->getString () : "";
+ std::replace (description.begin (), description.end (), '\n', ' ');
+
+ std::string license = "unknown";
+ auto licenseMeta = aMeta ? aMeta->maybeGetAttr ("license") : NULL;
+ if (licenseMeta) {
+ auto fullName = licenseMeta->maybeGetAttr ("fullName");
+ if (fullName)
+ license = fullName->getString ();
}

- string longDescription = drv.queryMetaString ("longDescription");
- if (longDescription == "")
- longDescription = drv.queryMetaString ("description");
-
- pk_backend_job_details (
- job,
- nix_drv_package_id (drv),
- drv.queryMetaString ("description").c_str (),
- license.c_str(),
- PK_GROUP_ENUM_UNKNOWN, // TODO: hack in group support
- longDescription.c_str (),
- drv.queryMetaString ("homepage").c_str (),
- 0
- );
+ auto aLongDescription = aMeta ? aMeta->maybeGetAttr ("longDescription") : NULL;
+ std::string longDescription = aLongDescription ? aLongDescription->getString () : "";
+
+ auto aHomepage = aMeta ? aMeta->maybeGetAttr ("homepage") : NULL;
+ std::string homepage = aHomepage ? aHomepage->getString () : "";
+
+ pk_backend_job_details (job,
+ package_ids[i],
+ description.c_str (),
+ license.c_str (),
+ PK_GROUP_ENUM_UNKNOWN,
+ longDescription.c_str (),
+ homepage.c_str (),
+ 0);
+ } else {
+ pk_backend_job_error_code (job,
+ PK_ERROR_ENUM_UNKNOWN,
+ "%s is not a package",
+ attrPath.c_str ());
+ return;
}
}
- catch (std::exception & e)
- {
- }

- pk_nix_finish (job, error);
+ pk_backend_job_set_percentage (job, 100);
}

void
pk_backend_get_details (PkBackend* backend, PkBackendJob* job, gchar** packages)
{
- pk_nix_run (job, PK_STATUS_ENUM_INFO, pk_backend_get_details_thread, packages);
+ pk_backend_job_set_status(job, PK_STATUS_ENUM_QUERY);
+ pk_backend_job_thread_create(job, pk_backend_get_details_thread, NULL, NULL);
}

-static void
-pk_backend_get_packages_thread (PkBackendJob* job, GVariant* params, gpointer p)
+static nix::Path
+nix_get_user_profile (PkBackendJob* job)
{
- g_autoptr (GError) error = NULL;
-
- PkBitfield filters;
- g_variant_get (params, "(t)", &filters);
+ guint uid = pk_backend_job_get_uid (job);

- try
- {
- // possibly slow call
- if (drvs.empty ())
- drvs = nix_get_all_derivations (*state, priv->roothome);
-
- auto profile = nix_get_profile (job);
- DrvInfos installedDrvs = queryInstalled (*state, profile);
-
- int n = 0;
- double percentFactor = 100 / drvs.size ();
-
- for (auto drv : drvs)
- {
- if (pk_backend_job_is_cancelled (job))
- break;
-
- pk_backend_job_set_percentage (job, (n++) * percentFactor);
-
- if (!nix_filter_drv (*state, drv, settings, filters))
- continue;
-
- auto info = PK_INFO_ENUM_AVAILABLE;
-
- for (auto _drv : installedDrvs)
- if (_drv.queryName() == drv.queryName())
- {
- info = PK_INFO_ENUM_INSTALLED;
- break;
- }
-
- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED) && info != PK_INFO_ENUM_INSTALLED)
- continue;
-
- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED) && info == PK_INFO_ENUM_INSTALLED)
- continue;
-
- pk_backend_job_package (
- job,
- info,
- nix_drv_package_id (drv),
- drv.queryMetaString ("description").c_str ()
- );
- }
- }
- catch (std::exception & e)
- {
- }
-
- pk_nix_finish (job, error);
-}
+ struct passwd* uid_ent = NULL;
+ if ((uid_ent = getpwuid (uid)) == NULL)
+ g_error ("Failed to get HOME");

-void
-pk_backend_get_packages (PkBackend* backend, PkBackendJob* job, PkBitfield filters)
-{
- pk_nix_run (job, PK_STATUS_ENUM_GENERATE_PACKAGE_LIST, pk_backend_get_packages_thread, NULL);
+ return std::string(uid_ent->pw_dir) + "/.nix-profile";
}

static void
-pk_backend_resolve_thread (PkBackendJob* job, GVariant* params, gpointer p)
+nix_search_thread (PkBackendJob* job, GVariant* params, gpointer p)
{
- g_autoptr (GError) error = NULL;
-
const gchar **search;
PkBitfield filters;
- g_variant_get (params, "(t^a&s)", &filters, &search);

- try
- {
- // possibly slow call
- if (drvs.empty ())
- drvs = nix_get_all_derivations (*state, priv->roothome);
-
- auto profile = nix_get_profile (job);
- DrvInfos installedDrvs = queryInstalled (*state, profile);
-
- for (; *search != NULL; ++search)
- {
- if (pk_backend_job_is_cancelled (job))
- break;
+ PkRoleEnum role = pk_backend_job_get_role (job);

- DrvName searchName (*search);
+ switch(role) {
+ case PK_ROLE_ENUM_GET_PACKAGES:
+ g_variant_get (params, "(t)", &filters);
+ break;
+ case PK_ROLE_ENUM_SEARCH_NAME:
+ case PK_ROLE_ENUM_SEARCH_DETAILS:
+ case PK_ROLE_ENUM_RESOLVE:
+ g_variant_get (params, "(t^a&s)", &filters, &search);
+ break;
+ default:
+ break;
+ }
+
+ std::string attrPath = "legacyPackages." + nix::settings.thisSystem.get () + ".";
+ auto cursor = nix_get_cursor (*priv->state, priv->defaultFlake, attrPath);
+
+ if (pk_backend_job_is_cancelled (job))
+ return;
+
+ std::vector<std::regex> regexes;
+ if (search)
+ for (; *search != NULL; search++)
+ regexes.push_back (std::regex (*search, std::regex::extended | std::regex::icase));
+
+ nix::DrvInfos installedDrvs;
+
+ if (pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED)
+ || pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED)) {
+ std::optional<nix::PathSet> oldAllowedPaths = priv->state->allowedPaths;
+ priv->state->allowedPaths = std::nullopt;
+
+ std::string userProfile = nix_get_user_profile (job);
+ if (nix::pathExists (userProfile + "/manifest.nix")) {
+ nix::Value v;
+ priv->state->evalFile (userProfile + "/manifest.nix", v);
+ nix::Bindings & bindings (*priv->state->allocBindings(0));
+ nix::getDerivations (*priv->state, v, "", bindings, installedDrvs, false);
+ }
+
+ std::string defaultProfile = nix::settings.nixStateDir + "/profiles/default";
+ if (nix::pathExists (defaultProfile + "/manifest.nix")) {
+ nix::Value v;
+ priv->state->evalFile (defaultProfile + "/manifest.nix", v);
+ nix::Bindings & bindings (*priv->state->allocBindings(0));
+ nix::getDerivations (*priv->state, v, "", bindings, installedDrvs, false);
+ }
+
+ priv->state->allowedPaths = oldAllowedPaths;
+ }
+
+ int totalDrvs = 0;
+ int foundDrvs = 0;
+
+ std::function<void(nix::eval_cache::AttrCursor & cursor, const std::vector<nix::Symbol> & attrPath)> visit;
+ visit = [&](nix::eval_cache::AttrCursor & cursor, const std::vector<nix::Symbol> & attrPath) {
+ try {
+ if (pk_backend_job_is_cancelled (job))
+ return;
+
+ auto recurse = [&] () {
+ auto attrs = cursor.getAttrs ();
+
+ totalDrvs += attrs.size();
+ if (totalDrvs > 0)
+ pk_backend_job_set_percentage (job, 100 * foundDrvs / totalDrvs);
+
+ for (const auto & attr : attrs) {
+ auto cursor2 = cursor.getAttr (attr);
+ auto attrPath2 (attrPath);
+ attrPath2.push_back (attr);
+ visit (*cursor2, attrPath2);
+ }
+ };

- for (auto drv : drvs)
- {
- DrvName drvName (drv.queryName());
- if (searchName.matches (drvName))
- {
- if (!nix_filter_drv (*state, drv, settings, filters))
- continue;
-
- auto info = PK_INFO_ENUM_AVAILABLE;
-
- for (auto _drv : installedDrvs)
- if (_drv.queryName() == drv.queryName())
- {
- info = PK_INFO_ENUM_INSTALLED;
- break;
- }
+ if (cursor.isDerivation ()) {
+ foundDrvs++;

- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED) && info != PK_INFO_ENUM_INSTALLED)
- continue;
+ size_t found = 0;

- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED) && info == PK_INFO_ENUM_INSTALLED)
- continue;
+ nix::DrvName name (cursor.getAttr ("name")->getString());

- pk_backend_job_package (
- job,
- info,
- nix_drv_package_id (drv),
- drv.queryMetaString ("description").c_str ()
- );
- }
- }
- }
- }
- catch (std::exception & e)
- {
- }
+ auto aMeta = cursor.maybeGetAttr ("meta");
+ auto aDescription = aMeta ? aMeta->maybeGetAttr ("description") : NULL;

- pk_nix_finish (job, error);
-}
+ auto description = aDescription ? aDescription->getString() : "";
+ std::replace (description.begin (), description.end (), '\n', ' ');

-void
-pk_backend_resolve (PkBackend* self, PkBackendJob* job, PkBitfield filters, gchar** search)
-{
- pk_nix_run (job, PK_STATUS_ENUM_QUERY, pk_backend_resolve_thread, NULL);
-}
+ auto attrPath2 = concatStringsSep (".", attrPath);

-static void
-pk_backend_search_names_thread (PkBackendJob* job, GVariant* params, gpointer p)
-{
- g_autoptr (GError) error = NULL;
-
- gchar **search;
- PkBitfield filters;
- g_variant_get (params, "(t^a&s)", &filters, &search);
-
- try
- {
- // possibly slow call
- if (drvs.empty ())
- drvs = nix_get_all_derivations (*state, priv->roothome);
-
- auto profile = nix_get_profile (job);
- DrvInfos installedDrvs = queryInstalled (*state, profile);
-
- for (; *search != NULL; ++search)
- {
- if (pk_backend_job_is_cancelled (job))
- break;
+ for (auto & regex : regexes) {
+ switch (role) {
+ case PK_ROLE_ENUM_SEARCH_NAME:
+ case PK_ROLE_ENUM_RESOLVE: {
+ std::smatch nameMatch;
+ std::regex_search (name.name, nameMatch, regex);
+ std::smatch attrMatch;
+ std::regex_search (attrPath2, attrMatch, regex);
+ if (!nameMatch.empty () || !attrMatch.empty())
+ found++;
+ break;
+ }
+ case PK_ROLE_ENUM_SEARCH_DETAILS: {
+ std::smatch descriptionMatch;
+ std::regex_search (description, descriptionMatch, regex);
+ if (!descriptionMatch.empty ())
+ found++;
+ break;
+ }
+ default:
+ found++;
+ break;
+ }
+ }

- for (auto drv : drvs)
- if (drv.queryName().find(*search) != -1)
- {
- if (!nix_filter_drv (*state, drv, settings, filters))
- continue;
-
- auto info = PK_INFO_ENUM_AVAILABLE;
-
- for (auto _drv : installedDrvs)
- if (_drv.queryName() == drv.queryName())
- {
- info = PK_INFO_ENUM_INSTALLED;
+ if (found == regexes.size () || regexes.empty ()) {
+ bool isInstalled = false;
+ for (auto drv : installedDrvs) {
+ if (nix::DrvName (drv.queryName ()).matches(name)) {
+ isInstalled = true;
break;
}
+ }

- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED) && info != PK_INFO_ENUM_INSTALLED)
- continue;
+ if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED) && isInstalled)
+ return;
+ if (pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED) && !isInstalled)
+ return;
+
+ auto available = aMeta ? aMeta->maybeGetAttr ("available") : NULL;
+ bool isSupported = available ? available->getBool () : true;
+
+ if (pk_bitfield_contain (filters, PK_FILTER_ENUM_SUPPORTED) && !isSupported)
+ return;
+ if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_SUPPORTED) && isSupported)
+ return;
+
+ std::string system = cursor.getAttr ("system")->getString();
+
+ PkInfoEnum info = PK_INFO_ENUM_UNKNOWN;
+ if (isSupported)
+ info = PK_INFO_ENUM_AVAILABLE;
+ if (isInstalled)
+ info = PK_INFO_ENUM_INSTALLED;
+
+ if (totalDrvs > 0)
+ pk_backend_job_set_percentage (job, 100 * foundDrvs / totalDrvs);
+
+ pk_backend_job_package (job,
+ info,
+ pk_package_id_build (attrPath2.c_str (),
+ name.version.c_str (),
+ system.c_str (),
+ priv->defaultFlake.c_str ()),
+ description.c_str());
+ }
+ }

- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED) && info == PK_INFO_ENUM_INSTALLED)
- continue;
+ else if (attrPath.size() == 0)
+ recurse();

- pk_backend_job_package (
- job,
- info,
- nix_drv_package_id (drv),
- drv.queryMetaString ("description").c_str ()
- );
- }
+ else if (attrPath.size() >= 1) {
+ auto attr = cursor.maybeGetAttr(priv->state->sRecurseForDerivations);
+ if (attr && attr->getBool())
+ recurse();
+ }
+ } catch (nix::EvalError & e) {
}
- }
- catch (std::exception & e)
- {
- }
-
- pk_nix_finish (job, error);
+ };
+ visit(*cursor, {});
+ pk_backend_job_set_percentage (job, 100);
}

void
-pk_backend_search_names (PkBackend *backend, PkBackendJob *job, PkBitfield filters, gchar **values)
+pk_backend_get_packages (PkBackend* backend, PkBackendJob* job, PkBitfield filters)
{
- pk_nix_run (job, PK_STATUS_ENUM_QUERY, pk_backend_search_names_thread, NULL);
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_GENERATE_PACKAGE_LIST);
+ pk_backend_job_thread_create(job, nix_search_thread, NULL, NULL);
}

-static void
-pk_backend_search_details_thread (PkBackendJob* job, GVariant* params, gpointer p)
-{
- g_autoptr (GError) error = NULL;
-
- gchar **value;
- PkBitfield filters;
- g_variant_get (params, "(t^a&s)", &filters, &value);
-
- try
- {
- // possibly slow call
- if (drvs.empty ())
- drvs = nix_get_all_derivations (*state, priv->roothome);
-
- auto profile = nix_get_profile (job);
- DrvInfos installedDrvs = queryInstalled (*state, profile);
-
- for (; *value != NULL; ++value)
- {
- if (pk_backend_job_is_cancelled (job))
- break;
-
- for (auto drv : drvs)
- if (drv.queryMetaString ("description").find (*value) != -1)
- {
- if (!nix_filter_drv (*state, drv, settings, filters))
- continue;
-
- auto info = PK_INFO_ENUM_AVAILABLE;
-
- for (auto _drv : installedDrvs)
- if (_drv.queryName() == drv.queryName())
- {
- info = PK_INFO_ENUM_INSTALLED;
- break;
- }
-
- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED) && info != PK_INFO_ENUM_INSTALLED)
- continue;
-
- if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED) && info == PK_INFO_ENUM_INSTALLED)
- continue;
-
- pk_backend_job_package (
- job,
- info,
- nix_drv_package_id (drv),
- drv.queryMetaString ("description").c_str ()
- );
- }
- }
- }
- catch (std::exception & e)
- {
- }
-
- pk_nix_finish (job, error);
+void
+pk_backend_search_names (PkBackend *backend, PkBackendJob *job, PkBitfield filters, gchar **values) {
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_QUERY);
+ pk_backend_job_thread_create (job, nix_search_thread, NULL, NULL);
}

void
pk_backend_search_details (PkBackend *backend, PkBackendJob *job, PkBitfield filters, gchar **values)
{
- pk_nix_run (job, PK_STATUS_ENUM_QUERY, pk_backend_search_details_thread, NULL);
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_QUERY);
+ pk_backend_job_thread_create (job, nix_search_thread, NULL, NULL);
}

-static void
-pk_backend_refresh_cache_thread (PkBackendJob* job, GVariant* params, gpointer p)
+void
+pk_backend_resolve(PkBackend* self, PkBackendJob* job, PkBitfield filters, gchar** search)
{
- g_autoptr (GError) error = NULL;
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_QUERY);
+ pk_backend_job_thread_create (job, nix_search_thread, NULL, NULL);
+}

- try
- {
- state = nix_get_state ();
- drvs = nix_get_all_derivations (*state, priv->roothome);
- }
- catch (std::exception & e)
- {
- }
+static void
+nix_refresh_thread (PkBackendJob* job, GVariant* params, gpointer p)
+{
+ nix::settings.tarballTtl = 0;
+ nix_search_thread (job, params, p);
+ nix::settings.tarballTtl = 60 * 60;

- pk_nix_finish (job, error);
+ pk_backend_job_set_percentage (job, 100);
}

void
pk_backend_refresh_cache (PkBackend* backend, PkBackendJob* job, gboolean force)
{
- pk_nix_run (job, PK_STATUS_ENUM_REFRESH_CACHE, pk_backend_refresh_cache_thread, NULL);
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_REFRESH_CACHE);
+ pk_backend_job_thread_create (job, nix_refresh_thread, NULL, NULL);
}

static void
-pk_backend_install_packages_thread (PkBackendJob* job, GVariant* params, gpointer p)
+nix_install_thread (PkBackendJob* job, GVariant* params, gpointer p)
{
- g_autoptr (GError) error = NULL;
-
PkBitfield flags;
gchar** package_ids;
-
g_variant_get (params, "(t^a&s)", &flags, &package_ids);

- try
- {
- // possibly slow call
- if (drvs.empty ())
- drvs = nix_get_all_derivations (*state, priv->roothome);
-
- DrvInfos newElems = nix_get_drvs_from_ids (*state, drvs, package_ids);
-
- for (auto drv : newElems)
- {
- pk_backend_job_package (
- job,
- PK_INFO_ENUM_INSTALLING,
- nix_drv_package_id (drv),
- drv.queryMetaString ("description").c_str ()
- );
- }
-
- Path profile = nix_get_profile (job);
-
- while (true)
- {
- if (pk_backend_job_is_cancelled (job))
- break;
+ nix::DrvInfos newElems;
+ gchar** parts;

- string lockToken = optimisticLockProfile (profile);
- DrvInfos allElems (newElems);
-
- DrvInfos installedElems = queryInstalled (*state, profile);
+ for (size_t i = 0; package_ids[i] != NULL; i++) {
+ if (pk_backend_job_is_cancelled (job))
+ return;
+
+ // we put the attr path in "PK_PACKAGE_ID_NAME" because that's how we identify it
+ parts = pk_package_id_split (package_ids[i]);
+ std::string attrPath = std::string (parts[PK_PACKAGE_ID_NAME]);
+ std::string flake = std::string (parts[PK_PACKAGE_ID_DATA]);
+ g_strfreev (parts);
+
+ auto cursor = nix_get_cursor (*priv->state, flake, "legacyPackages." + nix::settings.thisSystem.get () + "." + attrPath);
+
+ if (cursor && cursor->isDerivation ()) {
+ std::optional<nix::DrvInfo> drv;
+ drv = nix::getDerivation (*priv->state, cursor->forceValue(), false);
+ if (drv) {
+ auto aMeta = cursor->maybeGetAttr ("meta");
+ auto aDescription = aMeta ? aMeta->maybeGetAttr ("description") : NULL;
+ auto description = aDescription ? aDescription->getString() : "";
+
+ try {
+ drv->queryDrvPath ();
+ } catch (nix::Error & e) {
+ pk_backend_job_error_code (job,
+ PK_ERROR_ENUM_UNKNOWN,
+ "failed to evaluate %s",
+ attrPath.c_str ());
+ return;
+ }

- for (auto & i : installedElems)
- {
- DrvName drvName(i.queryName());
- allElems.push_back (i);
+ pk_backend_job_package (job,
+ PK_INFO_ENUM_INSTALLING,
+ package_ids[i],
+ description.c_str());
+ newElems.push_back (*drv);
+ } else {
+ pk_backend_job_error_code (job,
+ PK_ERROR_ENUM_UNKNOWN,
+ "failed to evaluate %s",
+ attrPath.c_str ());
+ return;
}
-
- if (createUserEnv (*state, allElems, profile, false, lockToken))
- break;
+ } else {
+ pk_backend_job_error_code (job,
+ PK_ERROR_ENUM_UNKNOWN,
+ "%s is not a package",
+ attrPath.c_str ());
+ return;
}
-
- for (auto drv : newElems)
- {
- pk_backend_job_package (
- job,
- PK_INFO_ENUM_INSTALLED,
- nix_drv_package_id (drv),
- drv.queryMetaString ("description").c_str ()
- );
- }
- }
- catch (std::exception & e)
- {
}

- pk_nix_finish (job, error);
-}
+ std::string profile = nix_get_user_profile (job);

-void
-pk_backend_install_packages (PkBackend* backend, PkBackendJob* job, PkBitfield transaction_flags, gchar** package_ids)
-{
- pk_nix_run (job, PK_STATUS_ENUM_INSTALL, pk_backend_install_packages_thread, NULL);
-}
+ std::optional<nix::PathSet> oldAllowedPaths = priv->state->allowedPaths;
+ priv->state->allowedPaths = std::nullopt;

-static void
-pk_backend_remove_packages_thread (PkBackendJob* job, GVariant* params, gpointer p)
-{
- g_autoptr (GError) error = NULL;
-
- PkBitfield transaction_flags;
- gchar** package_ids;
- gboolean allow_deps, autoremove;
- g_variant_get (params, "(t^a&sbb)", &transaction_flags, &package_ids, &allow_deps, &autoremove);
+ while (true) {
+ if (pk_backend_job_is_cancelled (job)) {
+ priv->state->allowedPaths = oldAllowedPaths;
+ return;
+ }

- try
- {
- // possibly slow call
- if (drvs.empty ())
- drvs = nix_get_all_derivations(*state, priv->roothome);
-
- DrvInfos _drvs = nix_get_drvs_from_ids (*state, drvs, package_ids);
-
- for (auto drv : _drvs)
- {
- pk_backend_job_package (
- job,
- PK_INFO_ENUM_REMOVING,
- nix_drv_package_id (drv),
- drv.queryMetaString ("description").c_str ()
- );
- }
-
- Path profile = nix_get_profile (job);
-
- while (true)
- {
- if (pk_backend_job_is_cancelled (job))
- break;
+ std::string lockToken = nix::optimisticLockProfile (profile);

- string lockToken = optimisticLockProfile (profile);
+ nix::DrvInfos allElems (newElems);

- DrvInfos installedElems = queryInstalled (*state, profile);
- DrvInfos newElems;
+ /* Add in the already installed derivations, unless they have
+ the same name as a to-be-installed element. */
+ nix::DrvInfos installedElems;
+ try {
+ installedElems = nix::queryInstalled (*priv->state, profile);
+ } catch (nix::Error & e) {
+ priv->state->allowedPaths = oldAllowedPaths;
+ pk_backend_job_error_code (job,
+ PK_ERROR_ENUM_UNKNOWN,
+ "failed to create new environment: %s", e.what ());
+ return;
+ }

- for (auto & drv : installedElems)
- {
- bool found = false;
-
- for (auto & _drv : _drvs)
- if (drv.attrPath == _drv.attrPath)
- {
- found = true;
- break;
- }
+ for (auto & i : installedElems) {
+ bool found = false;

- if (!found)
- newElems.push_back (drv);
+ for (auto & j : newElems) {
+ if (nix::DrvName(i.queryName ()).name == nix::DrvName (j.queryName ()).name) {
+ found = true;
+ break;
+ }
}

- if (createUserEnv (*state, newElems, profile, false, lockToken))
- break;
+ if (!found)
+ allElems.push_back (i);
}

- for (auto drv : _drvs)
- {
- pk_backend_job_package (
- job,
- PK_INFO_ENUM_AVAILABLE,
- nix_drv_package_id (drv),
- drv.queryMetaString ("description").c_str ()
- );
+ try {
+ if (nix::createUserEnv (*priv->state, allElems, profile, false, lockToken))
+ break;
+ } catch (nix::Error & e) {
+ priv->state->allowedPaths = oldAllowedPaths;
+ pk_backend_job_error_code (job,
+ PK_ERROR_ENUM_UNKNOWN,
+ "failed to create new environment: %s", e.what ());
+ return;
}
}
- catch (std::exception & e)
- {
- }

- pk_nix_finish (job, error);
+ priv->state->allowedPaths = oldAllowedPaths;
+
+ for (size_t i = 0; package_ids[i] != NULL; i++)
+ pk_backend_job_package (job, PK_INFO_ENUM_INSTALLED, package_ids[i], NULL);
+
+ pk_backend_job_set_percentage (job, 100);
}

void
-pk_backend_remove_packages (PkBackend* backend, PkBackendJob* job, PkBitfield transaction_flags, gchar** package_ids, gboolean allow_deps, gboolean autoremove)
+pk_backend_install_packages (PkBackend* backend, PkBackendJob* job, PkBitfield transaction_flags, gchar** package_ids)
{
- pk_nix_run (job, PK_STATUS_ENUM_REMOVE, pk_backend_remove_packages_thread, NULL);
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_INSTALL);
+ pk_backend_job_thread_create (job, nix_install_thread, NULL, NULL);
}

static void
-pk_backend_update_packages_thread (PkBackendJob* job, GVariant* params, gpointer p)
+nix_remove_thread (PkBackendJob* job, GVariant* params, gpointer p)
{
- g_autoptr (GError) error = NULL;
+ PkBitfield transaction_flags;
+ gchar** package_ids;
+ gboolean allow_deps, autoremove;
+ g_variant_get (params, "(t^a&sbb)", &transaction_flags, &package_ids, &allow_deps, &autoremove);

- try
- {
- // possibly slow call
- if (drvs.empty ())
- drvs = nix_get_all_derivations (*state, priv->roothome);
+ nix::Path profile = nix_get_user_profile (job);

- auto profile = nix_get_profile (job);
+ nix::DrvInfos elemsToDelete;
+ gchar** parts;

- while (true)
- {
- if (pk_backend_job_is_cancelled (job))
- break;
+ for (size_t i = 0; package_ids[i] != NULL; i++) {
+ // we put the attr path in "PK_PACKAGE_ID_NAME" because that's how we identify it
+ parts = pk_package_id_split (package_ids[i]);
+ std::string attrPath = std::string (parts[PK_PACKAGE_ID_NAME]);
+ std::string flake = std::string (parts[PK_PACKAGE_ID_DATA]);
+ g_strfreev (parts);
+
+ auto cursor = nix_get_cursor (*priv->state, flake, "legacyPackages." + nix::settings.thisSystem.get () + "." + attrPath);
+ if (cursor && cursor->isDerivation ()) {
+ auto drv = nix::getDerivation (*priv->state, cursor->forceValue(), false);
+ if (drv)
+ elemsToDelete.push_back (*drv);
+ else {
+ pk_backend_job_error_code (job,
+ PK_ERROR_ENUM_UNKNOWN,
+ "failed to evaluate %s",
+ attrPath.c_str ());
+ return;
+ }
+ } else {
+ pk_backend_job_error_code (job,
+ PK_ERROR_ENUM_UNKNOWN,
+ "%s is not a package",
+ attrPath.c_str ());
+ return;
+ }

- string lockToken = optimisticLockProfile (profile);
+ auto aMeta = cursor->maybeGetAttr ("meta");
+ auto aDescription = aMeta ? aMeta->maybeGetAttr ("description") : NULL;
+ auto description = aDescription ? aDescription->getString() : "";

- DrvInfos installedElems = queryInstalled (*state, profile);
+ pk_backend_job_package (job, PK_INFO_ENUM_REMOVING, package_ids[i], description.c_str());
+ }

- /* Go through all installed derivations. */
- DrvInfos newElems;
- for (auto & i : installedElems)
- {
- DrvName drvName (i.queryName());
-
- try
- {
- if (keep (i))
- {
- newElems.push_back (i);
- continue;
- }
+ std::optional<nix::PathSet> oldAllowedPaths = priv->state->allowedPaths;
+ priv->state->allowedPaths = std::nullopt;

- /* Find the derivation in the input Nix expression
- with the same name that satisfies the version
- constraints specified by upgradeType. If there are
- multiple matches, take the one with the highest
- priority. If there are still multiple matches,
- take the one with the highest version.
- Do not upgrade if it would decrease the priority. */
- DrvInfos::iterator bestElem = drvs.end ();
- string bestVersion;
-
- for (auto j = drvs.begin (); j != drvs.end (); ++j)
- {
- if (comparePriorities (*state, i, *j) > 0)
- continue;
-
- DrvName newName (j->queryName());
- if (newName.name == drvName.name)
- {
- int d = compareVersions (drvName.version, newName.version);
- if (d < 0)
- {
- int d2 = -1;
- if (bestElem != drvs.end ())
- {
- d2 = comparePriorities (*state, *bestElem, *j);
- if (d2 == 0)
- d2 = compareVersions (bestVersion, newName.version);
- }
- if (d2 < 0)
- {
- bestElem = j;
- bestVersion = newName.version;
- }
- }
- }
- }
+ while (true) {
+ if (pk_backend_job_is_cancelled (job)) {
+ priv->state->allowedPaths = oldAllowedPaths;
+ return;
+ }

- if (bestElem != drvs.end () && i.queryOutPath () != bestElem->queryOutPath ())
- {
- const char * action;
- auto _drv = *bestElem;
- if (compareVersions (drvName.version, bestVersion) <= 0)
- {
- pk_backend_job_package (
- job,
- PK_INFO_ENUM_UPDATING,
- nix_drv_package_id (_drv),
- _drv.queryMetaString ("description").c_str ()
- );
+ std::string lockToken = nix::optimisticLockProfile (profile);

- action = "upgrading";
- }
- else
- {
- pk_backend_job_package (
- job,
- PK_INFO_ENUM_DOWNGRADING,
- nix_drv_package_id (_drv),
- _drv.queryMetaString ("description").c_str ()
- );
+ nix::DrvInfos installedElems = nix::queryInstalled (*priv->state, profile);
+ nix::DrvInfos newElems;

- action = "downgrading";
- }
- newElems.push_back (*bestElem);
- }
- else
- newElems.push_back (i);
- }
- catch (Error & e)
- {
- throw;
- }
- }
+ for (auto & i : installedElems) {
+ bool found = false;

- if (createUserEnv (*state, newElems, profile, false, lockToken))
- {
- for (auto drv : newElems)
- {
- pk_backend_job_package (
- job,
- PK_INFO_ENUM_INSTALLED,
- nix_drv_package_id (drv),
- drv.queryMetaString ("description").c_str ()
- );
- }

- break;
+ for (auto & j : elemsToDelete) {
+ if (nix::DrvName (i.queryName ()).name == nix::DrvName (j.queryName ()).name) {
+ found = true;
+ break;
+ }
}
+
+ if (!found)
+ newElems.push_back (i);
}
- }
- catch (std::exception & e)
- {
+
+ if (nix::createUserEnv (*priv->state, newElems, profile, false, lockToken))
+ break;
}

- pk_nix_finish (job, error);
+ priv->state->allowedPaths = oldAllowedPaths;
+
+ for (size_t i = 0; package_ids[i] != NULL; i++)
+ pk_backend_job_package (job, PK_INFO_ENUM_AVAILABLE, package_ids[i], NULL);
+
+ pk_backend_job_set_percentage (job, 100);
+}
+
+void
+pk_backend_remove_packages (PkBackend* backend, PkBackendJob* job, PkBitfield transaction_flags, gchar** package_ids, gboolean allow_deps, gboolean autoremove)
+{
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_REMOVE);
+ pk_backend_job_thread_create (job, nix_remove_thread, NULL, NULL);
}

void
pk_backend_update_packages (PkBackend* backend, PkBackendJob* job, PkBitfield transaction_flags, gchar** package_ids)
{
- pk_nix_run (job, PK_STATUS_ENUM_UPDATE, pk_backend_update_packages_thread, NULL);
+ pk_backend_job_set_status (job, PK_STATUS_ENUM_UPDATE);
+ pk_backend_job_thread_create (job, nix_install_thread, NULL, NULL);
}

static void
-pk_backend_download_packages_thread (PkBackendJob* job, GVariant* params, gpointer p)
+nix_get_updates_thread (PkBackendJob* job, GVariant* params, gpointer p)
{
- g_autoptr (GError) error = NULL;
+ auto profile = nix_get_user_profile (job);

- gchar* directory;
- gchar** package_ids;
- g_variant_get (params, "(^a&ss)", &package_ids, &directory);
+ std::optional<nix::PathSet> oldAllowedPaths = priv->state->allowedPaths;
+ priv->state->allowedPaths = std::nullopt;

- try
- {
- // possibly slow call
- if (drvs.empty ())
- drvs = nix_get_all_derivations (*state, priv->roothome);
-
- DrvInfos _drvs = nix_get_drvs_from_ids (*state, drvs, package_ids);
-
- PathSet paths;
- for (auto drv : _drvs)
- {
- if (pk_backend_job_is_cancelled (job))
- break;
+ nix::DrvInfos installedElems = nix::queryInstalled (*priv->state, profile);

- pk_backend_job_package (
- job,
- PK_INFO_ENUM_DOWNLOADING,
- nix_drv_package_id (drv),
- drv.queryMetaString ("description").c_str ()
- );
-
- // should provide updates to status
- // just build one path at a time
- PathSet paths;
- paths.insert (drv.queryOutPath ());
- state->store->buildPaths (paths);
+ priv->state->allowedPaths = oldAllowedPaths;
+
+ int progress = 0;
+ for (auto & i : installedElems) {
+ pk_backend_job_set_percentage (job, 100 * progress++ / installedElems.size());
+
+ auto cursor = nix_get_cursor (*priv->state, priv->defaultFlake, "legacyPackages." + nix::settings.thisSystem.get () + "." + i.attrPath);
+ if (cursor && cursor->isDerivation ()) {
+ auto drv = nix::getDerivation (*priv->state, cursor->forceValue(), false);
+ if (drv && drv->queryDrvPath () != i.queryDrvPath ()) {
+ nix::DrvName name (drv->queryName ());
+ pk_backend_job_package (job,
+ PK_INFO_ENUM_NORMAL,
+ pk_package_id_build (drv->attrPath.c_str (),
+ name.version.c_str (),
+ drv->querySystem ().c_str (),
+ priv->defaultFlake.c_str ()),
+ drv->queryMetaString ("description").c_str ());
+ }
}
}
- catch (std::exception & e)
- {
- }

- pk_nix_finish (job, error);
+ pk_backend_job_set_percentage (job, 100);
}

void
-pk_backend_download_packages (PkBackend* backend, PkBackendJob* job, gchar** package_ids, const gchar* directory)
+pk_backend_get_updates(PkBackend *backend, PkBackendJob *job, PkBitfield filters)
{
- pk_nix_run (job, PK_STATUS_ENUM_DOWNLOAD, pk_backend_download_packages_thread, NULL);
+ pk_backend_job_set_status(job, PK_STATUS_ENUM_QUERY);
+ pk_backend_job_thread_create(job, nix_get_updates_thread, NULL, NULL);
}
diff -Nru packagekit-1.2.4/backends/slack/meson.build packagekit-1.2.4+git20220215/backends/slack/meson.build
--- packagekit-1.2.4/backends/slack/meson.build 2021-07-30 01:24:45.083523000 -0700
+++ packagekit-1.2.4+git20220215/backends/slack/meson.build 2022-02-15 11:44:24.000000000 -0800
@@ -1,6 +1,7 @@
add_languages('cpp')

curl_dep = meson.get_compiler('c').find_library('curl')
+bzip2_dep = dependency('bzip2')

packagekit_backend_slack_module = shared_module(
'pk_backend_slack',
@@ -15,6 +16,8 @@
packagekit_glib2_dep,
curl_dep,
gmodule_dep,
+ sqlite3_dep,
+ bzip2_dep,
],
cpp_args: [
'-DG_LOG_DOMAIN="PackageKit-Slackware"',
diff -Nru packagekit-1.2.4/backends/zypp/meson.build packagekit-1.2.4+git20220215/backends/zypp/meson.build
--- packagekit-1.2.4/backends/zypp/meson.build 2021-07-30 01:24:45.084523000 -0700
+++ packagekit-1.2.4+git20220215/backends/zypp/meson.build 2022-02-15 11:44:24.000000000 -0800
@@ -22,7 +22,8 @@
'-DG_LOG_DOMAIN="PackageKit-Zypp"',
'-Wall',
'-Woverloaded-virtual',
- '-Wnon-virtual-dtor'
+ '-Wnon-virtual-dtor',
+ '-std=c++1z'
],
c_args: [
'-Wno-deprecated',
diff -Nru packagekit-1.2.4/backends/zypp/pk-backend-zypp.cpp packagekit-1.2.4+git20220215/backends/zypp/pk-backend-zypp.cpp
--- packagekit-1.2.4/backends/zypp/pk-backend-zypp.cpp 2021-07-30 01:24:45.084523000 -0700
+++ packagekit-1.2.4+git20220215/backends/zypp/pk-backend-zypp.cpp 2022-02-15 11:44:24.000000000 -0800
@@ -2746,7 +2746,6 @@
PoolStatusSaver saver;
pk_backend_job_set_percentage (job, 10);
vector<PoolItem> items;
- VersionRelation relations[g_strv_length (package_ids)];
guint to_install = 0;

for (guint i = 0; package_ids[i]; i++) {
@@ -2776,43 +2775,45 @@
}
}

+ VersionRelation relation = NEWER_VERSION;
+
for (guint j = 0; j < installed.size (); j++) {
inst_pkg = &installed.at (j);
ret = inst_pkg->edition ().compare (Edition (split[PK_PACKAGE_ID_VERSION]));

- if (relations[i] == 0 && ret < 0) {
- relations[i] = NEWER_VERSION;
- } else if (relations[i] != EQUAL_VERSION && ret > 0) {
- relations[i] = OLDER_VERSION;
+ if (ret < 0) {
+ relation = NEWER_VERSION;
+ } else if (relation != EQUAL_VERSION && ret > 0) {
+ relation = OLDER_VERSION;
if (!latest_pkg ||
latest_pkg->edition ().compare (inst_pkg->edition ()) < 0) {
latest_pkg = inst_pkg;
}
} else if (ret == 0) {
- relations[i] = EQUAL_VERSION;
+ relation = EQUAL_VERSION;
break;
}
}

- if (relations[i] == EQUAL_VERSION &&
+ if (relation == EQUAL_VERSION &&
!pk_bitfield_contain (transaction_flags,
PK_TRANSACTION_FLAG_ENUM_ALLOW_REINSTALL)) {
continue;
}

- if (relations[i] == OLDER_VERSION &&
+ if (relation == OLDER_VERSION &&
!pk_bitfield_contain (transaction_flags,
PK_TRANSACTION_FLAG_ENUM_ALLOW_DOWNGRADE)) {
pk_backend_job_error_code (job,
PK_ERROR_ENUM_PACKAGE_ALREADY_INSTALLED,
"higher version \"%s\" of package %s.%s is already installed",
- latest_pkg->edition ().version ().c_str (),
+ latest_pkg ? latest_pkg->edition ().version ().c_str () : "<NULL>",
split[PK_PACKAGE_ID_NAME],
split[PK_PACKAGE_ID_ARCH]);
return;
}

- if (relations[i] && relations[i] != EQUAL_VERSION &&
+ if (relation != EQUAL_VERSION && installed.size() > 0 &&
pk_bitfield_contain (transaction_flags,
PK_TRANSACTION_FLAG_ENUM_JUST_REINSTALL)) {
pk_backend_job_error_code (job,
@@ -3088,6 +3089,12 @@
&_filters,
&values);

+ if (values == NULL && values[0] == NULL) {
+ pk_backend_job_error_code (job, PK_ERROR_ENUM_PACKAGE_ID_INVALID,
+ "Empty search string is not supported.");
+ return;
+ }
+
ZyppJob zjob(job);
ZYpp::Ptr zypp = zjob.get_zypp();

diff -Nru packagekit-1.2.4/client/pk-console.c packagekit-1.2.4+git20220215/client/pk-console.c
--- packagekit-1.2.4/client/pk-console.c 2021-07-30 01:24:45.085523000 -0700
+++ packagekit-1.2.4+git20220215/client/pk-console.c 2022-02-15 11:44:24.000000000 -0800
@@ -2283,14 +2283,14 @@
} else if (strcmp (mode, "offline-trigger") == 0) {

run_mainloop = FALSE;
- ret = pk_offline_trigger (PK_OFFLINE_ACTION_REBOOT, NULL, &error);
+ ret = pk_offline_trigger_with_flags (PK_OFFLINE_ACTION_REBOOT, PK_OFFLINE_FLAGS_INTERACTIVE, NULL, &error);
if (!ret)
ctx->retval = error->code;

} else if (strcmp (mode, "offline-cancel") == 0) {

run_mainloop = FALSE;
- ret = pk_offline_cancel (NULL, &error);
+ ret = pk_offline_cancel_with_flags (PK_OFFLINE_FLAGS_INTERACTIVE, NULL, &error);
if (!ret)
ctx->retval = error->code;

diff -Nru packagekit-1.2.4/contrib/command-not-found/meson.build packagekit-1.2.4+git20220215/contrib/command-not-found/meson.build
--- packagekit-1.2.4/contrib/command-not-found/meson.build 2021-07-30 01:24:45.085523000 -0700
+++ packagekit-1.2.4+git20220215/contrib/command-not-found/meson.build 2022-02-15 11:44:24.000000000 -0800
@@ -7,7 +7,7 @@
c_args: [
'-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()),
'-DG_LOG_DOMAIN="PackageKit"',
- '-DPACKAGE_LOCALE_DIR="@0@"'.format(get_option('localedir')),
+ '-DPACKAGE_LOCALE_DIR="@0@"'.format(join_paths(get_option('prefix'), get_option('localedir'))),
'-DSYSCONFDIR="@0@"'.format(get_option('sysconfdir')),
]
)
diff -Nru packagekit-1.2.4/contrib/command-not-found/PackageKit.sh.in packagekit-1.2.4+git20220215/contrib/command-not-found/PackageKit.sh.in
--- packagekit-1.2.4/contrib/command-not-found/PackageKit.sh.in 2021-07-30 01:24:45.085523000 -0700
+++ packagekit-1.2.4+git20220215/contrib/command-not-found/PackageKit.sh.in 2022-02-15 11:44:24.000000000 -0800
@@ -30,7 +30,7 @@
'@LIBEXECDIR@/pk-command-not-found' "$@"
retval=$?
elif [[ -n "${BASH_VERSION-}" ]]; then
- printf >&2 'bash: %scommand not found\n' "${1:+$1: }"
+ printf >&2 'bash: %s%s\n' "${1:+$1: }" "$(gettext PackageKit 'command not found')"
fi

# return success or failure
diff -Nru packagekit-1.2.4/data/packagekit.service.in packagekit-1.2.4+git20220215/data/packagekit.service.in
--- packagekit-1.2.4/data/packagekit.service.in 2021-07-30 01:24:45.087523000 -0700
+++ packagekit-1.2.4+git20220215/data/packagekit.service.in 2022-02-15 11:44:24.000000000 -0800
@@ -4,6 +4,7 @@
# currently the design is to have dedicated daemons like
# eos-updater and rpm-ostree, and gnome-software talks to those.
ConditionPathExists=!/run/ostree-booted
+Wants=network-online.target

[Service]
Type=dbus
diff -Nru packagekit-1.2.4/debian/changelog packagekit-1.2.4+git20220215/debian/changelog
--- packagekit-1.2.4/debian/changelog 2022-01-13 08:51:50.000000000 -0800
+++ packagekit-1.2.4+git20220215/debian/changelog 2022-02-15 11:34:29.000000000 -0800
@@ -1,3 +1,9 @@
+packagekit (1.2.4+git20220215-0ubuntu1) jammy; urgency=medium
+
+ * Git snapshot to include apt auto/manual resolution fix (LP: #1914278)
+
+ -- Erich Eickmeyer <eeickmeyer@ubuntu.com> Tue, 15 Feb 2022 11:34:29 -0800
+
packagekit (1.2.4-1ubuntu1) jammy; urgency=low

* Merge from Debian unstable. Remaining changes:
diff -Nru packagekit-1.2.4/docs/api/PackageKit-sections.txt packagekit-1.2.4+git20220215/docs/api/PackageKit-sections.txt
--- packagekit-1.2.4/docs/api/PackageKit-sections.txt 2021-07-30 01:24:45.087523000 -0700
+++ packagekit-1.2.4+git20220215/docs/api/PackageKit-sections.txt 2022-02-15 11:44:24.000000000 -0800
@@ -525,9 +525,13 @@
pk_offline_get_results
pk_offline_get_results_mtime
pk_offline_cancel
+pk_offline_cancel_with_flags
pk_offline_clear_results
+pk_offline_clear_results_with_flags
pk_offline_trigger
+pk_offline_trigger_with_flags
pk_offline_trigger_upgrade
+pk_offline_trigger_upgrade_with_flags
</SECTION>

<SECTION>
diff -Nru packagekit-1.2.4/docs/html/pk-users.html packagekit-1.2.4+git20220215/docs/html/pk-users.html
--- packagekit-1.2.4/docs/html/pk-users.html 2021-07-30 01:24:45.095522900 -0700
+++ packagekit-1.2.4+git20220215/docs/html/pk-users.html 2022-02-15 11:44:24.000000000 -0800
@@ -131,15 +131,15 @@
</tr>
<tr>
<td>
- <a href="http://kde-apps.org/content/show.php/Apper?content=84745"><img src="img/users-apper.png" alt=""/></a>
+ <a href="https://apps.kde.org/discover/"><img src="https://apps.kde.org/app-icons/org.kde.discover.svg" alt=""/></a>
</td>
<td>
- <h2>KDE - Apper</h2>
+ <h2>KDE - Discover</h2>
<p>
- Apper is the KDE interface for PackageKit.
+ Discover is the KDE interface for PackageKit.
</p>
<p>
- Supports PackageKit >= 0.6.18
+ Supports PackageKit >= 1.0.1
</p>
</td>
</tr>
diff -Nru packagekit-1.2.4/.editorconfig packagekit-1.2.4+git20220215/.editorconfig
--- packagekit-1.2.4/.editorconfig 1969-12-31 16:00:00.000000000 -0800
+++ packagekit-1.2.4+git20220215/.editorconfig 2022-02-15 11:44:24.000000000 -0800
@@ -0,0 +1,27 @@
+# See https://editorconfig.org/
+root = true
+
+[*]
+end_of_line = lf
+trim_trailing_whitespace = true
+charset = utf-8
+
+[*.{c,h}]
+indent_style = tab
+indent_size = 8
+
+[*.cpp]
+indent_style = space
+indent_size = 4
+
+[*.sh]
+indent_style = space
+indent_size = 4
+
+[*.xml]
+indent_style = space
+indent_size = 4
+
+[meson.build]
+indent_style = space
+indent_size = 4
diff -Nru packagekit-1.2.4/.git/config packagekit-1.2.4+git20220215/.git/config
--- packagekit-1.2.4/.git/config 1969-12-31 16:00:00.000000000 -0800
+++ packagekit-1.2.4+git20220215/.git/config 2022-02-15 11:44:24.000000000 -0800
@@ -0,0 +1,11 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ logallrefupdates = true
+[remote "origin"]
+ url = https://github.com/PackageKit/PackageKit.git
+ fetch = +refs/heads/*:refs/remotes/origin/*
+[branch "main"]
+ remote = origin
+ merge = refs/heads/main
diff -Nru packagekit-1.2.4/.git/description packagekit-1.2.4+git20220215/.git/description
--- packagekit-1.2.4/.git/description 1969-12-31 16:00:00.000000000 -0800
+++ packagekit-1.2.4+git20220215/.git/description 2022-02-15 11:44:19.000000000 -0800
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff -Nru packagekit-1.2.4/.git/HEAD packagekit-1.2.4+git20220215/.git/HEAD
--- packagekit-1.2.4/.git/HEAD 1969-12-31 16:00:00.000000000 -0800
+++ packagekit-1.2.4+git20220215/.git/HEAD 2022-02-15 11:44:24.000000000 -0800
@@ -0,0 +1 @@
+ref: refs/heads/main
Binary files /tmp/JziqiOyaEG/packagekit-1.2.4/.git/index and /tmp/lKkw0BlWoA/packagekit-1.2.4+git20220215/.git/index differ
diff -Nru packagekit-1.2.4/.git/info/exclude packagekit-1.2.4+git20220215/.git/info/exclude
--- packagekit-1.2.4/.git/info/exclude 1969-12-31 16:00:00.000000000 -0800
+++ packagekit-1.2.4+git20220215/.git/info/exclude 2022-02-15 11:44:19.000000000 -0800
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff -Nru packagekit-1.2.4/.git/logs/HEAD packagekit-1.2.4+git20220215/.git/logs/HEAD
--- packagekit-1.2.4/.git/logs/HEAD 1969-12-31 16:00:00.000000000 -0800
+++ packagekit-1.2.4+git20220215/.git/logs/HEAD 2022-02-15 11:44:24.000000000 -0800
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 3b3d435ea5c136000d311b085cfc0bbd34bf4264 Erich Eickmeyer <erich@ericheickmeyer.com> 1644954264 -0800 clone: from https://github.com/PackageKit/PackageKit.git
diff -Nru packagekit-1.2.4/.git/logs/refs/heads/main packagekit-1.2.4+git20220215/.git/logs/refs/heads/main
--- packagekit-1.2.4/.git/logs/refs/heads/main 1969-12-31 16:00:00.000000000 -0800
+++ packagekit-1.2.4+git20220215/.git/logs/refs/heads/main 2022-02-15 11:44:24.000000000 -0800
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 3b3d435ea5c136000d311b085cfc0bbd34bf4264 Erich Eickmeyer <erich@ericheickmeyer.com> 1644954264 -0800 clone: from https://github.com/PackageKit/PackageKit.git
diff -Nru packagekit-1.2.4/.git/logs/refs/remotes/origin/HEAD packagekit-1.2.4+git20220215/.git/logs/refs/remotes/origin/HEAD
--- packagekit-1.2.4/.git/logs/refs/remotes/origin/HEAD 1969-12-31 16:00:00.000000000 -0800
+++ packagekit-1.2.4+git20220215/.git/logs/refs/remotes/origin/HEAD 2022-02-15 11:44:24.000000000 -0800
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 3b3d435ea5c136000d311b085cfc0bbd34bf4264 Erich Eickmeyer <erich@ericheickmeyer.com> 1644954264 -0800 clone: from https://github.com/PackageKit/PackageKit.git
Binary files /tmp/JziqiOyaEG/packagekit-1.2.4/.git/objects/pack/pack-a2550873ddf24a7102d4dd3935b86302930d9732.idx and /tmp/lKkw0BlWoA/packagekit-1.2.4+git20220215/.git/objects/pack/pack-a2550873ddf24a7102d4dd3935b86302930d9732.idx differ
Binary files /tmp/JziqiOyaEG/packagekit-1.2.4/.git/objects/pack/pack-a2550873ddf24a7102d4dd3935b86302930d9732.pack and /tmp/lKkw0BlWoA/packagekit-1.2.4+git20220215/.git/objects/pack/pack-a2550873ddf24a7102d4dd3935b86302930d9732.pack differ
diff -Nru packagekit-1.2.4/.git/refs/heads/main packagekit-1.2.4+git20220215/.git/refs/heads/main
--- packagekit-1.2.4/.git/refs/heads/main 1969-12-31 16:00:00.000000000 -0800
+++ packagekit-1.2.4+git20220215/.git/refs/heads/main 2022-02-15 11:44:24.000000000 -0800
@@ -0,0 +1 @@
+3b3d435ea5c136000d311b085cfc0bbd34bf4264
diff -Nru packagekit-1.2.4/.git/refs/remotes/origin/HEAD packagekit-1.2.4+git20220215/.git/refs/remotes/origin/HEAD
--- packagekit-1.2.4/.git/refs/remotes/origin/HEAD 1969-12-31 16:00:00.000000000 -0800
+++ packagekit-1.2.4+git20220215/.git/refs/remotes/origin/HEAD 2022-02-15 11:44:24.000000000 -0800
@@ -0,0 +1 @@
+ref: refs/remotes/origin/main
diff -Nru packagekit-1.2.4/.github/workflows/main.yml packagekit-1.2.4+git20220215/.github/workflows/main.yml
--- packagekit-1.2.4/.github/workflows/main.yml 1969-12-31 16:00:00.000000000 -0800
+++ packagekit-1.2.4+git20220215/.github/workflows/main.yml 2022-02-15 11:44:24.000000000 -0800
@@ -0,0 +1,22 @@
+name: Build and Test
+
+on: [push, pull_request]
+
+jobs:
+ build_and_test:
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ distro:
+ - fedora
+ - debian
+ fail-fast: false
+
+ steps:
+ - uses: actions/checkout@v2
+ - run: docker build -t packagekit-${{ matrix.distro }} -f tests/ci/Dockerfile-${{ matrix.distro }} .
+ - run: docker run -t -v `pwd`:/build packagekit-${{ matrix.distro }} ./tests/ci/build_and_test.sh -Dpackaging_backend=dnf
+ if: ${{ matrix.distro == 'fedora' }}
+ - run: docker run -t -v `pwd`:/build packagekit-${{ matrix.distro }} ./tests/ci/build_and_test.sh -Dpackaging_backend=aptcc
+ if: ${{ matrix.distro == 'debian' }}
diff -Nru packagekit-1.2.4/lib/packagekit-glib2/pk-offline.c packagekit-1.2.4+git20220215/lib/packagekit-glib2/pk-offline.c
--- packagekit-1.2.4/lib/packagekit-glib2/pk-offline.c 2021-07-30 01:24:45.105522900 -0700
+++ packagekit-1.2.4+git20220215/lib/packagekit-glib2/pk-offline.c 2022-02-15 11:44:24.000000000 -0800
@@ -95,6 +95,14 @@
return PK_OFFLINE_ACTION_UNKNOWN;
}

+static GDBusCallFlags
+pk_offline_flags_to_gdbus_call_flags (PkOfflineFlags flags)
+{
+ if ((flags & PK_OFFLINE_FLAGS_INTERACTIVE) != 0)
+ return G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION;
+ return G_DBUS_CALL_FLAGS_NONE;
+}
+
/**
* pk_offline_cancel:
* @cancellable: A #GCancellable or %NULL
@@ -102,6 +110,8 @@
*
* Cancels the offline operation that has been scheduled. If there is no
* scheduled offline operation then this method returns with success.
+ * The function always allows user interaction. To change the behavior,
+ * use pk_offline_cancel_with_flags().
*
* Return value: %TRUE for success, else %FALSE and @error set
*
@@ -110,6 +120,25 @@
gboolean
pk_offline_cancel (GCancellable *cancellable, GError **error)
{
+ return pk_offline_cancel_with_flags (PK_OFFLINE_FLAGS_INTERACTIVE, cancellable, error);
+}
+
+/**
+ * pk_offline_cancel_with_flags:
+ * @flags: bit-or of #PkOfflineFlags
+ * @cancellable: A #GCancellable or %NULL
+ * @error: A #GError or %NULL
+ *
+ * Cancels the offline operation that has been scheduled. If there is no
+ * scheduled offline operation then this method returns with success.
+ *
+ * Return value: %TRUE for success, else %FALSE and @error set
+ *
+ * Since: 1.2.5
+ **/
+gboolean
+pk_offline_cancel_with_flags (PkOfflineFlags flags, GCancellable *cancellable, GError **error)
+{
g_autoptr(GDBusConnection) connection = NULL;
g_autoptr(GVariant) res = NULL;

@@ -125,7 +154,7 @@
"Cancel",
NULL,
NULL,
- G_DBUS_CALL_FLAGS_NONE,
+ pk_offline_flags_to_gdbus_call_flags (flags),
-1,
cancellable,
error);
@@ -139,8 +168,10 @@
* @cancellable: A #GCancellable or %NULL
* @error: A #GError or %NULL
*
- * Crears the last offline operation report, which may be success or failure.
+ * Clears the last offline operation report, which may be success or failure.
* If the report does not exist then this method returns success.
+ * The function always allows user interaction. To change the behavior,
+ * use pk_offline_clear_results_with_flags().
*
* Return value: %TRUE for success, else %FALSE and @error set
*
@@ -149,6 +180,25 @@
gboolean
pk_offline_clear_results (GCancellable *cancellable, GError **error)
{
+ return pk_offline_clear_results_with_flags (PK_OFFLINE_FLAGS_INTERACTIVE, cancellable, error);
+}
+
+/**
+ * pk_offline_clear_results_with_flags:
+ * @flags: bit-or of #PkOfflineFlags
+ * @cancellable: A #GCancellable or %NULL
+ * @error: A #GError or %NULL
+ *
+ * Clears the last offline operation report, which may be success or failure.
+ * If the report does not exist then this method returns success.
+ *
+ * Return value: %TRUE for success, else %FALSE and @error set
+ *
+ * Since: 1.2.5
+ **/
+gboolean
+pk_offline_clear_results_with_flags (PkOfflineFlags flags, GCancellable *cancellable, GError **error)
+{
g_autoptr(GDBusConnection) connection = NULL;
g_autoptr(GVariant) res = NULL;

@@ -164,7 +214,7 @@
"ClearResults",
NULL,
NULL,
- G_DBUS_CALL_FLAGS_NONE,
+ pk_offline_flags_to_gdbus_call_flags (flags),
-1,
cancellable,
error);
@@ -181,6 +231,8 @@
*
* Triggers the offline update so that the next reboot will perform the
* pending transaction.
+ * The function always allows user interaction. To change the behavior,
+ * use pk_offline_trigger_with_flags().
*
* Return value: %TRUE for success, else %FALSE and @error set
*
@@ -189,6 +241,26 @@
gboolean
pk_offline_trigger (PkOfflineAction action, GCancellable *cancellable, GError **error)
{
+ return pk_offline_trigger_with_flags (action, PK_OFFLINE_FLAGS_INTERACTIVE, cancellable, error);
+}
+
+/**
+ * pk_offline_trigger_with_flags:
+ * @action: a #PkOfflineAction, e.g. %PK_OFFLINE_ACTION_REBOOT
+ * @flags: bit-or of #PkOfflineFlags
+ * @cancellable: A #GCancellable or %NULL
+ * @error: A #GError or %NULL
+ *
+ * Triggers the offline update so that the next reboot will perform the
+ * pending transaction.
+ *
+ * Return value: %TRUE for success, else %FALSE and @error set
+ *
+ * Since: 1.2.5
+ **/
+gboolean
+pk_offline_trigger_with_flags (PkOfflineAction action, PkOfflineFlags flags, GCancellable *cancellable, GError **error)
+{
const gchar *tmp;
g_autoptr(GDBusConnection) connection = NULL;
g_autoptr(GVariant) res = NULL;
@@ -206,7 +278,7 @@
"Trigger",
g_variant_new ("(s)", tmp),
NULL,
- G_DBUS_CALL_FLAGS_NONE,
+ pk_offline_flags_to_gdbus_call_flags (flags),
-1,
cancellable,
error);
@@ -223,6 +295,8 @@
*
* Triggers the offline system upgrade so that the next reboot will perform the
* pending transaction.
+ * The function always allows user interaction. To change the behavior,
+ * use pk_offline_trigger_upgrade_with_flags().
*
* Return value: %TRUE for success, else %FALSE and @error set
*
@@ -231,6 +305,26 @@
gboolean
pk_offline_trigger_upgrade (PkOfflineAction action, GCancellable *cancellable, GError **error)
{
+ return pk_offline_trigger_upgrade_with_flags (action, PK_OFFLINE_FLAGS_INTERACTIVE, cancellable, error);
+}
+
+/**
+ * pk_offline_trigger_upgrade_with_flags:
+ * @action: a #PkOfflineAction, e.g. %PK_OFFLINE_ACTION_REBOOT
+ * @flags: bit-or of #PkOfflineFlags
+ * @cancellable: A #GCancellable or %NULL
+ * @error: A #GError or %NULL
+ *
+ * Triggers the offline system upgrade so that the next reboot will perform the
+ * pending transaction.
+ *
+ * Return value: %TRUE for success, else %FALSE and @error set
+ *
+ * Since: 1.2.5
+ **/
+gboolean
+pk_offline_trigger_upgrade_with_flags (PkOfflineAction action, PkOfflineFlags flags, GCancellable *cancellable, GError **error)
+{
const gchar *tmp;
g_autoptr(GDBusConnection) connection = NULL;
g_autoptr(GVariant) res = NULL;
@@ -248,7 +342,7 @@
"TriggerUpgrade",
g_variant_new ("(s)", tmp),
NULL,
- G_DBUS_CALL_FLAGS_NONE,
+ pk_offline_flags_to_gdbus_call_flags (flags),
-1,
cancellable,
error);
diff -Nru packagekit-1.2.4/lib/packagekit-glib2/pk-offline.h packagekit-1.2.4+git20220215/lib/packagekit-glib2/pk-offline.h
--- packagekit-1.2.4/lib/packagekit-glib2/pk-offline.h 2021-07-30 01:24:45.106523000 -0700
+++ packagekit-1.2.4+git20220215/lib/packagekit-glib2/pk-offline.h 2022-02-15 11:44:24.000000000 -0800
@@ -71,6 +71,21 @@
PK_OFFLINE_ERROR_LAST
} PkOfflineError;

+/**
+ * PkOfflineFlags:
+ * @PK_OFFLINE_FLAGS_NONE: No specific flag
+ * @PK_OFFLINE_FLAGS_INTERACTIVE: Run the action in an interactive mode, allowing polkit authentication dialogs
+ *
+ * Flags to be used for the method invocations.
+ *
+ * Since: 1.2.5
+ */
+typedef enum
+{
+ PK_OFFLINE_FLAGS_NONE = 0,
+ PK_OFFLINE_FLAGS_INTERACTIVE = 1 << 0
+} PkOfflineFlags;
+
GQuark pk_offline_error_quark (void);
const gchar *pk_offline_action_to_string (PkOfflineAction action);
PkOfflineAction pk_offline_action_from_string (const gchar *action);
@@ -92,14 +107,30 @@
guint64 pk_offline_get_results_mtime (GError **error);
gboolean pk_offline_cancel (GCancellable *cancellable,
GError **error);
+gboolean pk_offline_cancel_with_flags (PkOfflineFlags flags,
+ GCancellable *cancellable,
+ GError **error);
gboolean pk_offline_clear_results (GCancellable *cancellable,
GError **error);
+gboolean pk_offline_clear_results_with_flags
+ (PkOfflineFlags flags,
+ GCancellable *cancellable,
+ GError **error);
gboolean pk_offline_trigger (PkOfflineAction action,
GCancellable *cancellable,
GError **error);
+gboolean pk_offline_trigger_with_flags (PkOfflineAction action,
+ PkOfflineFlags flags,
+ GCancellable *cancellable,
+ GError **error);
gboolean pk_offline_trigger_upgrade (PkOfflineAction action,
GCancellable *cancellable,
GError **error);
+gboolean pk_offline_trigger_upgrade_with_flags
+ (PkOfflineAction action,
+ PkOfflineFlags flags,
+ GCancellable *cancellable,
+ GError **error);

G_END_DECLS

diff -Nru packagekit-1.2.4/lib/packagekit-glib2/pk-test-daemon.c packagekit-1.2.4+git20220215/lib/packagekit-glib2/pk-test-daemon.c
--- packagekit-1.2.4/lib/packagekit-glib2/pk-test-daemon.c 2021-07-30 01:24:45.108523000 -0700
+++ packagekit-1.2.4+git20220215/lib/packagekit-glib2/pk-test-daemon.c 2022-02-15 11:44:24.000000000 -0800
@@ -154,7 +154,7 @@
g_assert_cmpstr (data, ==, "powertop;1.8-1.fc8;i386;fedora");

/* trigger */
- ret = pk_offline_trigger (PK_OFFLINE_ACTION_REBOOT, NULL, &error);
+ ret = pk_offline_trigger_with_flags (PK_OFFLINE_ACTION_REBOOT, PK_OFFLINE_FLAGS_INTERACTIVE, NULL, &error);
g_assert_no_error (error);
g_assert (ret);
g_assert (g_file_test (PK_OFFLINE_PREPARED_FILENAME, G_FILE_TEST_EXISTS));
@@ -163,7 +163,7 @@
g_assert (!g_file_test (PK_OFFLINE_RESULTS_FILENAME, G_FILE_TEST_EXISTS));

/* cancel the trigger */
- ret = pk_offline_cancel (NULL, &error);
+ ret = pk_offline_cancel_with_flags (PK_OFFLINE_FLAGS_INTERACTIVE, NULL, &error);
g_assert_no_error (error);
g_assert (ret);
g_assert (g_file_test (PK_OFFLINE_PREPARED_FILENAME, G_FILE_TEST_EXISTS));
diff -Nru packagekit-1.2.4/meson.build packagekit-1.2.4+git20220215/meson.build
--- packagekit-1.2.4/meson.build 2021-07-30 01:24:45.110523000 -0700
+++ packagekit-1.2.4+git20220215/meson.build 2022-02-15 11:44:24.000000000 -0800
@@ -1,5 +1,5 @@
project('PackageKit', 'c',
- version : '1.2.4',
+ version : '1.2.5',
license : 'LGPL-2.1+',
meson_version : '>=0.50',
default_options : ['warning_level=2', 'c_std=c99'],
diff -Nru packagekit-1.2.4/RELEASE packagekit-1.2.4+git20220215/RELEASE
--- packagekit-1.2.4/RELEASE 2021-07-30 01:24:45.075523000 -0700
+++ packagekit-1.2.4+git20220215/RELEASE 2022-02-15 11:44:24.000000000 -0800
@@ -2,10 +2,10 @@

1. Write NEWS entries for PackageKit in the same format as usual.

-git shortlog PACKAGEKIT_1_2_3.. | grep -i -v trivial | grep -v Merge > NEWS.new
+git shortlog PACKAGEKIT_1_2_4.. | grep -i -v trivial | grep -v Merge > NEWS.new

--------------------------------------------------------------------------------
-Version 1.2.4
+Version 1.2.5
~~~~~~~~~~~~~
Released: 2021-xx-xx

@@ -33,8 +33,8 @@
4. Commit changes in PackageKit git:

# MAKE SURE THESE ARE CORRECT
-export release_version="1.2.4"
-export release_tag="PACKAGEKIT_1_2_4"
+export release_version="1.2.5"
+export release_tag="PACKAGEKIT_1_2_5"

git commit -a -m "Release ${release_version}"
git tag -s -f -m "Release ${release_version}" "${release_tag}"
@@ -65,7 +65,7 @@
9. Send an email to packagekit@lists.freedesktop.org

=================================================
-PackageKit 1.2.4 released!
+PackageKit 1.2.5 released!

Tarballs available here: http://www.freedesktop.org/software/PackageKit/releases/

On Tue, 2022-02-15 at 10:33 -0800, Brian Murray wrote:
> From what you've said this sounds like something worth carrying as a
> debdiff in packagekit rather than waiting for Debian to fix it.
> Additionally, it'd make sense to me to get this sorted out for stable
> releases of Ubuntu too. Is there any work being done on that front?

Hi Brian,

Attached is the requested debdiff. In order for the changes to be
relevant, it had to be a git snapshot. That said, the git snapshot is
very close to what will be released as part of PackageKit 1.2.5 when it
releases. Matthias Klump (ximion) has been very helpful and is planning
this release in the very near future. This .debdiff is also uploaded
and attached to LP: #1914278.

I imagine when it lands I can provide a new .debdiff for upload, unless
it lands in Debian prior to Beta Freeze, at which point I think we can
simply sync it.

Let me know if you need anything else on this front. I imagine Julian
will want to be in on this too, so CC'd.

Erich

--
Erich Eickmeyer
Project Leader, Ubuntu Studio
Member, Ubuntu Community Council
>