316 lines
7.7 KiB
C
316 lines
7.7 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
|
*
|
|
* Copyright (C) 2014 Richard Hughes <richard@hughsie.com>
|
|
*
|
|
* Licensed under the GNU Lesser General Public License Version 2.1
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <glib.h>
|
|
#include <glib/gstdio.h>
|
|
#include <libhif-private.h>
|
|
|
|
#include <hawkey/errno.h>
|
|
|
|
#include "hif-backend.h"
|
|
|
|
/**
|
|
* hif_rc_to_error_enum:
|
|
*/
|
|
PkErrorEnum
|
|
hif_rc_to_error_enum (gint rc)
|
|
{
|
|
PkErrorEnum error_enum;
|
|
|
|
g_assert (rc != 0);
|
|
switch (rc) {
|
|
case HY_E_OP: /* client programming error */
|
|
case HY_E_LIBSOLV: /* error propagated from libsolv */
|
|
case HY_E_IO: /* I/O error */
|
|
case HY_E_CACHE_WRITE: /* cache write error */
|
|
case HY_E_QUERY: /* ill-formed query */
|
|
case HY_E_ARCH: /* unknown arch */
|
|
case HY_E_VALIDATION: /* validation check failed */
|
|
case HY_E_SELECTOR: /* ill-specified selector */
|
|
case HY_E_NO_SOLUTION: /* goal found no solutions */
|
|
case HY_E_FAILED: /* general runtime error */
|
|
default:
|
|
error_enum = HIF_ERROR_INTERNAL_ERROR;
|
|
break;
|
|
}
|
|
return error_enum;
|
|
}
|
|
|
|
/**
|
|
* hif_rc_to_error_str:
|
|
*/
|
|
const gchar *
|
|
hif_rc_to_error_str (gint rc)
|
|
{
|
|
const gchar *str;
|
|
|
|
g_assert (rc != 0);
|
|
switch (rc) {
|
|
case HY_E_FAILED:
|
|
str = "general runtime error";
|
|
break;
|
|
case HY_E_OP:
|
|
str = "client programming error";
|
|
break;
|
|
case HY_E_LIBSOLV:
|
|
str = "error propagated from libsolv";
|
|
break;
|
|
case HY_E_IO:
|
|
str = "I/O error";
|
|
break;
|
|
case HY_E_CACHE_WRITE:
|
|
str = "cache write error";
|
|
break;
|
|
case HY_E_QUERY:
|
|
str = "ill-formed query";
|
|
break;
|
|
case HY_E_ARCH:
|
|
str = "unknown arch";
|
|
break;
|
|
case HY_E_VALIDATION:
|
|
str = "validation check failed";
|
|
break;
|
|
case HY_E_SELECTOR:
|
|
str = "ill-specified selector";
|
|
break;
|
|
case HY_E_NO_SOLUTION:
|
|
str = "goal found no solutions";
|
|
break;
|
|
default:
|
|
str = "no matching error enum";
|
|
break;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
/**
|
|
* hif_emit_package:
|
|
*/
|
|
void
|
|
hif_emit_package (PkBackendJob *job, PkInfoEnum info, HyPackage pkg)
|
|
{
|
|
/* detect */
|
|
if (info == PK_INFO_ENUM_UNKNOWN)
|
|
info = hif_package_get_info (pkg);
|
|
if (info == PK_INFO_ENUM_UNKNOWN)
|
|
info = hy_package_installed (pkg) ? PK_INFO_ENUM_INSTALLED : PK_INFO_ENUM_AVAILABLE;
|
|
pk_backend_job_package (job,
|
|
info,
|
|
hif_package_get_id (pkg),
|
|
hy_package_get_summary (pkg));
|
|
}
|
|
|
|
/**
|
|
* hif_emit_package_list:
|
|
*/
|
|
void
|
|
hif_emit_package_list (PkBackendJob *job,
|
|
PkInfoEnum info,
|
|
HyPackageList pkglist)
|
|
{
|
|
guint i;
|
|
HyPackage pkg;
|
|
|
|
FOR_PACKAGELIST(pkg, pkglist, i)
|
|
hif_emit_package (job, info, pkg);
|
|
}
|
|
|
|
/**
|
|
* hif_emit_package_array:
|
|
*/
|
|
void
|
|
hif_emit_package_array (PkBackendJob *job,
|
|
PkInfoEnum info,
|
|
GPtrArray *array)
|
|
{
|
|
guint i;
|
|
HyPackage pkg;
|
|
|
|
for (i = 0; i < array->len; i++) {
|
|
pkg = g_ptr_array_index (array, i);
|
|
hif_emit_package (job, info, pkg);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* hif_emit_package_list_filter:
|
|
*/
|
|
void
|
|
hif_emit_package_list_filter (PkBackendJob *job,
|
|
PkBitfield filters,
|
|
HyPackageList pkglist)
|
|
{
|
|
GHashTable *hash_cost;
|
|
GHashTable *hash_installed;
|
|
HyPackage found;
|
|
HyPackage pkg;
|
|
guint i;
|
|
|
|
/* if a package exists in multiple repos, show the one with the lowest
|
|
* cost of downloading */
|
|
hash_cost = g_hash_table_new (g_str_hash, g_str_equal);
|
|
FOR_PACKAGELIST(pkg, pkglist, i) {
|
|
if (hy_package_installed (pkg))
|
|
continue;
|
|
|
|
/* if the NEVRA does not already exist in the array, just add */
|
|
found = g_hash_table_lookup (hash_cost,
|
|
hif_package_get_nevra (pkg));
|
|
if (found == NULL) {
|
|
g_hash_table_insert (hash_cost,
|
|
(gpointer) hif_package_get_nevra (pkg),
|
|
(gpointer) pkg);
|
|
continue;
|
|
}
|
|
|
|
/* a lower cost package */
|
|
if (hif_package_get_cost (pkg) < hif_package_get_cost (found)) {
|
|
hif_package_set_info (found, PK_INFO_ENUM_BLOCKED);
|
|
g_hash_table_replace (hash_cost,
|
|
(gpointer) hif_package_get_nevra (pkg),
|
|
(gpointer) pkg);
|
|
} else {
|
|
hif_package_set_info (pkg, PK_INFO_ENUM_BLOCKED);
|
|
}
|
|
}
|
|
|
|
/* add all the installed packages to a hash */
|
|
hash_installed = g_hash_table_new (g_str_hash, g_str_equal);
|
|
FOR_PACKAGELIST(pkg, pkglist, i) {
|
|
if (!hy_package_installed (pkg))
|
|
continue;
|
|
g_hash_table_insert (hash_installed,
|
|
(gpointer) hif_package_get_nevra (pkg),
|
|
(gpointer) pkg);
|
|
}
|
|
|
|
FOR_PACKAGELIST(pkg, pkglist, i) {
|
|
|
|
/* blocked */
|
|
if ((PkInfoEnum) hif_package_get_info (pkg) == PK_INFO_ENUM_BLOCKED)
|
|
continue;
|
|
|
|
/* GUI */
|
|
if (pk_bitfield_contain (filters, PK_FILTER_ENUM_GUI) && !hif_package_is_gui (pkg))
|
|
continue;
|
|
if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_GUI) && hif_package_is_gui (pkg))
|
|
continue;
|
|
|
|
/* DEVELOPMENT */
|
|
if (pk_bitfield_contain (filters, PK_FILTER_ENUM_DEVELOPMENT) && !hif_package_is_devel (pkg))
|
|
continue;
|
|
if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_DEVELOPMENT) && hif_package_is_devel (pkg))
|
|
continue;
|
|
|
|
/* DOWNLOADED */
|
|
if (pk_bitfield_contain (filters, PK_FILTER_ENUM_DOWNLOADED) && !hif_package_is_downloaded (pkg))
|
|
continue;
|
|
if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_DOWNLOADED) && hif_package_is_downloaded (pkg))
|
|
continue;
|
|
|
|
/* if this package is available and the very same NEVRA is
|
|
* installed, skip this package */
|
|
if (!hy_package_installed (pkg)) {
|
|
found = g_hash_table_lookup (hash_installed,
|
|
hif_package_get_nevra (pkg));
|
|
if (found != NULL)
|
|
continue;
|
|
}
|
|
|
|
hif_emit_package (job, PK_INFO_ENUM_UNKNOWN, pkg);
|
|
}
|
|
g_hash_table_unref (hash_cost);
|
|
g_hash_table_unref (hash_installed);
|
|
}
|
|
|
|
/**
|
|
* hif_update_severity_to_info_enum:
|
|
*/
|
|
PkInfoEnum
|
|
hif_update_severity_to_info_enum (HyUpdateSeverity severity)
|
|
{
|
|
PkInfoEnum info_enum = HY_UPDATE_SEVERITY_UNKNOWN;
|
|
switch (severity) {
|
|
case HY_UPDATE_SEVERITY_SECURITY:
|
|
info_enum = PK_INFO_ENUM_SECURITY;
|
|
break;
|
|
case HY_UPDATE_SEVERITY_IMPORTANT:
|
|
info_enum = PK_INFO_ENUM_IMPORTANT;
|
|
break;
|
|
case HY_UPDATE_SEVERITY_BUGFIX:
|
|
info_enum = PK_INFO_ENUM_BUGFIX;
|
|
break;
|
|
case HY_UPDATE_SEVERITY_NORMAL:
|
|
case HY_UPDATE_SEVERITY_UNKNOWN:
|
|
info_enum = PK_INFO_ENUM_NORMAL;
|
|
break;
|
|
case HY_UPDATE_SEVERITY_ENHANCEMENT:
|
|
info_enum = PK_INFO_ENUM_ENHANCEMENT;
|
|
break;
|
|
case HY_UPDATE_SEVERITY_LOW:
|
|
info_enum = PK_INFO_ENUM_LOW;
|
|
break;
|
|
default:
|
|
g_warning ("Failed to find HyUpdateSeverity enum %i", severity);
|
|
break;
|
|
}
|
|
return info_enum;
|
|
}
|
|
|
|
/**
|
|
* hif_get_filter_for_ids:
|
|
*/
|
|
PkBitfield
|
|
hif_get_filter_for_ids (gchar **package_ids)
|
|
{
|
|
gboolean available = FALSE;
|
|
gboolean installed = FALSE;
|
|
gchar **split;
|
|
guint i;
|
|
PkBitfield filters;
|
|
|
|
for (i = 0; package_ids[i] != NULL && (!installed || !available); i++) {
|
|
split = pk_package_id_split (package_ids[i]);
|
|
if (g_strcmp0 (split[PK_PACKAGE_ID_DATA], "installed") == 0)
|
|
installed = TRUE;
|
|
else
|
|
available = TRUE;
|
|
g_strfreev (split);
|
|
}
|
|
|
|
/* a mixture */
|
|
if (installed && available) {
|
|
filters = pk_bitfield_value (PK_FILTER_ENUM_NONE);
|
|
goto out;
|
|
}
|
|
|
|
/* we can restrict what's loaded into the sack */
|
|
if (!installed)
|
|
filters = pk_bitfield_value (PK_FILTER_ENUM_NOT_INSTALLED);
|
|
if (!available)
|
|
filters = pk_bitfield_value (PK_FILTER_ENUM_INSTALLED);
|
|
out:
|
|
return filters;
|
|
}
|