From 415856bdd4f48ab4f2732996f0bae58595092bbe Mon Sep 17 00:00:00 2001 From: Parabola Date: Tue, 5 Apr 2011 14:26:38 +0000 Subject: Tue Apr 5 14:26:38 UTC 2011 --- community/packagekit/PKGBUILD | 93 + community/packagekit/alpm.patch | 11693 ++++++++++++++++++++++++++++++ community/packagekit/packagekit.install | 11 + 3 files changed, 11797 insertions(+) create mode 100644 community/packagekit/PKGBUILD create mode 100644 community/packagekit/alpm.patch create mode 100644 community/packagekit/packagekit.install (limited to 'community/packagekit') diff --git a/community/packagekit/PKGBUILD b/community/packagekit/PKGBUILD new file mode 100644 index 000000000..410da5d19 --- /dev/null +++ b/community/packagekit/PKGBUILD @@ -0,0 +1,93 @@ +# $Id: PKGBUILD 43963 2011-04-01 10:59:14Z jconder $ +# Maintainer: Jonathan Conder +pkgbase='packagekit' +pkgname=('packagekit' 'packagekit-qt' 'packagekit-python') +pkgver=0.6.13 +pkgrel=2 +pkgdesc="A system designed to make installation and updates of packages easier." +arch=('i686' 'x86_64') +url="http://www.packagekit.org" +license=('GPL') +makedepends=('dbus-glib' 'gobject-introspection' 'gtk-doc' 'intltool' + 'networkmanager' 'pacman' 'pm-utils' 'polkit' 'python2' 'qt' + 'sqlite3') +options=('!libtool') +source=("http://www.packagekit.org/releases/PackageKit-$pkgver.tar.bz2" + 'alpm.patch') +sha256sums=('cec67a54cd615163402b1e5100a6a9be0bd1838896d6183407b4d9274de47249' + '777b1cda90f8cc78eb5cf651d47b5c7b6f183a34b98ad0d93945c76973bd29de') + +build() { + cd "$srcdir/PackageKit-$pkgver" + + patch -Np1 -i "$srcdir/alpm.patch" + + # TODO: change to Makefile.in's and configure + sed -i 's@SUBDIRS = test@SUBDIRS =@' 'backends/Makefile.am' + sed -i 's@python @python2 @' 'lib/python/packagekit/Makefile.am' + + export PYTHON=/usr/bin/python2 + ./autogen.sh --prefix=/usr \ + --sysconfdir=/etc \ + --localstatedir=/var \ + --libexecdir=/usr/lib/PackageKit \ + --disable-static \ + --disable-gtk-doc \ + --disable-tests \ + --disable-local \ + --disable-browser-plugin \ + --disable-gstreamer-plugin \ + --disable-gtk-module \ + --disable-command-not-found \ + --disable-cron \ + --disable-debuginfo-install \ + --enable-pm-utils \ + --disable-dummy \ + --enable-alpm \ + --with-default-backend=alpm + make +} + +package_packagekit() { + backup=('var/lib/PackageKit/transactions.db' + 'etc/PackageKit/alpm.d/pacman.conf' + 'etc/PackageKit/alpm.d/repos.list') + depends=('dbus-glib' 'pacman>=3.5.0' 'pacman<3.6.0' 'polkit' + 'shared-mime-info' 'sqlite3') + optdepends=('networkmanager') + install='packagekit.install' + + cd "$srcdir/PackageKit-$pkgver" + + make DESTDIR="$pkgdir" install + + rm -rf "$pkgdir/usr/include/PackageKit/packagekit-qt" + rm -rf "$pkgdir/usr/lib/libpackagekit-qt.so"* + rm -rf "$pkgdir/usr/lib/pkgconfig/packagekit-qt.pc" + rm -rf "$pkgdir/usr/share/cmake" + + rm -rf "$pkgdir/usr/lib/python"* + rm -rf "$pkgdir/usr/share/PackageKit/website" + + mv "$pkgdir/etc/bash_completion.d/pk-completion.bash" \ + "$pkgdir/etc/bash_completion.d/pkcon" + touch "$pkgdir/var/log/PackageKit" +} + +package_packagekit-qt() { + depends=('packagekit' 'qt') + pkgdesc=('Qt bindings for PackageKit') + + cd "$srcdir/PackageKit-$pkgver/lib/packagekit-qt" + + make DESTDIR="$pkgdir" install +} + +package_packagekit-python() { + depends=('packagekit' 'python2') + pkgdesc=('Python bindings for PackageKit') + + cd "$srcdir/PackageKit-$pkgver/lib/python" + + make DESTDIR="$pkgdir" install +} diff --git a/community/packagekit/alpm.patch b/community/packagekit/alpm.patch new file mode 100644 index 000000000..cc415ce9d --- /dev/null +++ b/community/packagekit/alpm.patch @@ -0,0 +1,11693 @@ +diff --git a/backends/Makefile.am b/backends/Makefile.am +index 3d53950..ba378df 100644 +--- a/backends/Makefile.am ++++ b/backends/Makefile.am +@@ -32,10 +32,6 @@ if BACKEND_TYPE_OPKG + SUBDIRS += opkg + endif + +-if BACKEND_TYPE_PACMAN +-SUBDIRS += pacman +-endif +- + if BACKEND_TYPE_RAZOR + SUBDIRS += razor + endif +diff --git a/backends/alpm/Makefile.am b/backends/alpm/Makefile.am +index 15749dc..a664b2c 100644 +--- a/backends/alpm/Makefile.am ++++ b/backends/alpm/Makefile.am +@@ -1,10 +1,54 @@ +-INCLUDES = \ +- -DG_LOG_DOMAIN=\"PackageKit-Alpm\" ++PK_BACKEND_CONFIG_FILE = $(confdir)/pacman.conf ++PK_BACKEND_GROUP_FILE = $(confdir)/groups.list ++PK_BACKEND_REPO_FILE = $(confdir)/repos.list ++ ++PK_BACKEND_DEFAULT_PATH = "/bin:/usr/bin:/sbin:/usr/sbin" ++PK_BACKEND_DEFAULT_ROOT = "/" ++PK_BACKEND_DEFAULT_DBPATH = $(localstatedir)/lib/pacman ++PK_BACKEND_DEFAULT_CACHEDIR = $(localstatedir)/cache/pacman/pkg ++PK_BACKEND_DEFAULT_LOGFILE = $(localstatedir)/log/pacman.log ++ ++ALPM_CACHE_PATH = $(localstatedir)/lib/pacman/sync ++ALPM_PACKAGE_URL = "http://www.archlinux.org/packages/%s/%s/%s/" ++ ++DEFS = -DPK_BACKEND_CONFIG_FILE=\"$(PK_BACKEND_CONFIG_FILE)\" \ ++ -DPK_BACKEND_GROUP_FILE=\"$(PK_BACKEND_GROUP_FILE)\" \ ++ -DPK_BACKEND_REPO_FILE=\"$(PK_BACKEND_REPO_FILE)\" \ ++ -DPK_BACKEND_DEFAULT_PATH=\"$(PK_BACKEND_DEFAULT_PATH)\" \ ++ -DPK_BACKEND_DEFAULT_ROOT=\"$(PK_BACKEND_DEFAULT_ROOT)\" \ ++ -DPK_BACKEND_DEFAULT_DBPATH=\"$(PK_BACKEND_DEFAULT_DBPATH)\" \ ++ -DPK_BACKEND_DEFAULT_CACHEDIR=\"$(PK_BACKEND_DEFAULT_CACHEDIR)\" \ ++ -DPK_BACKEND_DEFAULT_LOGFILE=\"$(PK_BACKEND_DEFAULT_LOGFILE)\" \ ++ -DALPM_CACHE_PATH=\"$(ALPM_CACHE_PATH)\" \ ++ -DALPM_PACKAGE_URL=\"$(ALPM_PACKAGE_URL)\" \ ++ -DG_LOG_DOMAIN=\"PackageKit-alpm\" ++ ++confdir = $(PK_CONF_DIR)/alpm.d ++conf_DATA = groups.list \ ++ pacman.conf \ ++ repos.list + + plugindir = $(PK_PLUGIN_DIR) + plugin_LTLIBRARIES = libpk_backend_alpm.la +-libpk_backend_alpm_la_SOURCES = pk-backend-alpm.c +-libpk_backend_alpm_la_LIBADD = $(PK_PLUGIN_LIBS) -lalpm +-libpk_backend_alpm_la_LDFLAGS = -module -avoid-version +-libpk_backend_alpm_la_CFLAGS = $(PK_PLUGIN_CFLAGS) $(WARNINGFLAGS_C) + ++libpk_backend_alpm_la_SOURCES = pk-backend-alpm.c \ ++ pk-backend-config.c \ ++ pk-backend-databases.c \ ++ pk-backend-depends.c \ ++ pk-backend-error.c \ ++ pk-backend-groups.c \ ++ pk-backend-install.c \ ++ pk-backend-packages.c \ ++ pk-backend-remove.c \ ++ pk-backend-search.c \ ++ pk-backend-sync.c \ ++ pk-backend-transaction.c \ ++ pk-backend-update.c ++libpk_backend_alpm_la_LIBADD = $(PK_PLUGIN_LIBS) \ ++ -lalpm ++libpk_backend_alpm_la_LDFLAGS = -module \ ++ -avoid-version ++libpk_backend_alpm_la_CFLAGS = $(PK_PLUGIN_CFLAGS) \ ++ $(WARNINGFLAGS_C) ++ ++EXTRA_DIST = $(conf_DATA) $(libpk_backend_alpm_la_SOURCES:.c=.h) +diff --git a/backends/alpm/TODO b/backends/alpm/TODO +deleted file mode 100644 +index 04a827f..0000000 +--- a/backends/alpm/TODO ++++ /dev/null +@@ -1,4 +0,0 @@ +- +-* Fix cache refreshing. Currently throws 'unexpected error' +-* Improve error handling by using macros. Currently 50% is very similiar error handling code. +-* Handle transaction progress and events in the callback functions. +diff --git a/backends/alpm/groups.list b/backends/alpm/groups.list +new file mode 100644 +index 0000000..b2c02ae +--- /dev/null ++++ b/backends/alpm/groups.list +@@ -0,0 +1,65 @@ ++adesklet-desklets desktop-other ++base system ++base-devel programming ++bmp-io-plugins multimedia ++bmp-plugins multimedia ++cegcc programming ++compiz desktop-other ++compiz-fusion desktop-other ++compiz-fusion-gtk desktop-gnome ++compiz-fusion-kde desktop-kde ++compiz-gnome desktop-gnome ++compiz-gtk desktop-gnome ++compiz-kde desktop-kde ++e17-extra-svn desktop-other ++e17-libs-svn desktop-other ++e17-svn desktop-other ++fprint other ++gimp-help other ++gimp-plugins other ++gnome desktop-gnome ++gnome-extra desktop-gnome ++gnustep-core desktop-other ++google-gadgets desktop-other ++gstreamer0.10-plugins multimedia ++kde desktop-kde ++kdeaccessibility desktop-kde ++kdeadmin desktop-kde ++kdeartwork desktop-kde ++kdebase desktop-kde ++kdeedu desktop-kde ++kde-extragear desktop-kde ++kdegames desktop-kde ++kdegraphics desktop-kde ++kde-l10n desktop-kde ++kde-meta desktop-kde ++kdemultimedia desktop-kde ++kdenetwork desktop-kde ++kdepim desktop-kde ++kdeplasma-addons desktop-kde ++kdesdk desktop-kde ++kdetoys desktop-kde ++kdeutils desktop-kde ++kdewebdev desktop-kde ++koffice desktop-kde ++ladspa-plugins multimedia ++lib32 other ++lxde other ++qtcurve desktop-kde ++rox-desktop desktop-other ++telepathy other ++texlive-lang other ++texlive-lang-doc other ++texlive-most other ++texlive-most-doc other ++thunderbird-i18n other ++thunderbird-spell-i18n other ++vim-plugins other ++xfce4 desktop-xfce ++xfce4-goodies desktop-xfce ++xmms-effect-plugins multimedia ++xmms-io-plugins multimedia ++xmms-plugins multimedia ++xorg desktop-other ++xorg-input-drivers desktop-other ++xorg-video-drivers desktop-other +diff --git a/backends/alpm/pacman.conf b/backends/alpm/pacman.conf +new file mode 100644 +index 0000000..8fdef09 +--- /dev/null ++++ b/backends/alpm/pacman.conf +@@ -0,0 +1,12 @@ ++# PackageKit configuration for the alpm backend ++# See the pacman.conf(5) manpage for option and repository directives. ++ ++[options] ++ ++# Use default pacman configuration initially ++# ++Include = /etc/pacman.conf ++ ++# Prevent PackageKit from removing itself ++# ++HoldPkg = packagekit +diff --git a/backends/alpm/pk-backend-alpm.c b/backends/alpm/pk-backend-alpm.c +index 5513d8d..0077329 100644 +--- a/backends/alpm/pk-backend-alpm.c ++++ b/backends/alpm/pk-backend-alpm.c +@@ -1,7 +1,8 @@ + /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder + * + * Licensed under the GNU General Public License Version 2 + * +@@ -20,1678 +21,361 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +-#define _GNU_SOURCE ++#include ++#include ++#include + +-#define ALPM_CONFIG_PATH "/etc/pacman.conf" ++#include "pk-backend-alpm.h" ++#include "pk-backend-databases.h" ++#include "pk-backend-error.h" ++#include "pk-backend-groups.h" + +-#define ALPM_ROOT "/" +-#define ALPM_DBPATH "/var/lib/pacman" +-#define ALPM_CACHEDIR "/var/cache/pacman/pkg" +-#define ALPM_LOGFILE "/var/log/pacman.log" ++PkBackend *backend = NULL; ++GCancellable *cancellable = NULL; ++static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + +-#define ALPM_PKG_EXT ".pkg.tar.gz" +-#define ALPM_LOCAL_DB_ALIAS "installed" ++pmdb_t *localdb = NULL; + +-#define ALPM_PROGRESS_UPDATE_INTERVAL 400 ++gchar *xfercmd = NULL; ++alpm_list_t *holdpkgs = NULL; ++alpm_list_t *syncfirsts = NULL; + +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-PkBackend *backend_instance = NULL; +- +-GHashTable *group_map; +- +-alpm_list_t *syncfirst = NULL; +-alpm_list_t *holdpkg = NULL; +- +-alpm_list_t *downloaded_files = NULL; +-gchar *current_file = NULL; +- +-off_t trans_xfered; +-off_t trans_total; +- +-int trans_subprogress; +- +-typedef enum { +- PK_ALPM_SEARCH_TYPE_NULL, +- PK_ALPM_SEARCH_TYPE_RESOLVE, +- PK_ALPM_SEARCH_TYPE_NAME, +- PK_ALPM_SEARCH_TYPE_DETAILS, +- PK_ALPM_SEARCH_TYPE_GROUP, +- PK_ALPM_SEARCH_TYPE_PROVIDES +-} PkAlpmSearchType; +- +-static int +-pkg_cmp (pmpkg_t *pkg1, pmpkg_t *pkg2) { +- int comparison; +- /* check for no package */ +- if (pkg1 == NULL) +- return -1; +- if (pkg2 == NULL) +- return 1; +- /* compare package names */ +- comparison = g_strcmp0 (alpm_pkg_get_name (pkg1), alpm_pkg_get_name (pkg2)); +- if (comparison != 0) +- return comparison; +- /* compare package versions */ +- comparison = alpm_pkg_vercmp (alpm_pkg_get_version (pkg1), alpm_pkg_get_version (pkg2)); +- if (comparison != 0) +- return comparison; +- /* packages are equal */ +- return 0; +-} +- +-/* temporary commented to not produce compilation errors :) */ +-/* +-static gboolean +-pkg_equal (pmpkg_t *p1, pmpkg_t *p2) +-{ +- if (g_strcmp0 (alpm_pkg_get_name (p1), alpm_pkg_get_name (p2)) != 0) +- return FALSE; +- if (g_strcmp0 (alpm_pkg_get_version (p1), alpm_pkg_get_version (p2)) != 0) +- return FALSE; +- return TRUE; +-} +-*/ +- +-static gboolean +-pkg_equals_to (pmpkg_t *pkg, const gchar *name, const gchar *version) +-{ +- if (pkg == NULL) +- return FALSE; +- if (g_strcmp0 (alpm_pkg_get_name (pkg), name) != 0) +- return FALSE; +- if (version != NULL) +- if (g_strcmp0 (alpm_pkg_get_version (pkg), version) != 0) +- return FALSE; +- return TRUE; +-} +- +-static gchar * +-pkg_to_package_id_str (pmpkg_t *pkg, const gchar *repo) +-{ +- gchar *arch = (gchar *) alpm_pkg_get_arch (pkg); +- if (arch == NULL) +- arch = (gchar *) "unknown"; +- +- return pk_package_id_build (alpm_pkg_get_name (pkg), alpm_pkg_get_version (pkg), arch, repo); +-} +- +-static pmpkg_t * +-pkg_from_package_id (const gchar *package_id) +-{ +- pmdb_t *repo = NULL; +- pmpkg_t *result; +- gchar **package_id_data = pk_package_id_split (package_id); +- +- /* do all this fancy stuff */ +- if (g_strcmp0 (ALPM_LOCAL_DB_ALIAS, package_id_data[PK_PACKAGE_ID_DATA]) == 0) +- repo = alpm_option_get_localdb (); +- else { +- alpm_list_t *iterator; +- for (iterator = alpm_option_get_syncdbs (); iterator; iterator = alpm_list_next (iterator)) { +- repo = alpm_list_getdata (iterator); +- if (g_strcmp0 (alpm_db_get_name (repo), package_id_data[PK_PACKAGE_ID_DATA]) == 0) +- break; +- } +- } +- +- if (repo != NULL) { +- pmpkg_t *pkg = alpm_db_get_pkg (repo, package_id_data[PK_PACKAGE_ID_NAME]); +- if (pkg_equals_to (pkg, package_id_data[PK_PACKAGE_ID_NAME], package_id_data[PK_PACKAGE_ID_VERSION])) +- result = pkg; +- else +- result = NULL; +- } else +- result = NULL; +- +- g_strfreev (package_id_data); +- +- return result; +-} +- +-static void +-emit_package (PkBackend *backend, pmpkg_t *pkg, const gchar *repo, PkInfoEnum info) +-{ +- gchar *package_id_str; +- +- g_debug ("alpm: emitting package with name %s", alpm_pkg_get_name (pkg)); +- +- package_id_str = pkg_to_package_id_str (pkg, repo); +- pk_backend_package (backend, info, package_id_str, alpm_pkg_get_desc (pkg)); +- g_free (package_id_str); +-} +- +-static void +-cb_trans_evt (pmtransevt_t event, void *data1, void *data2) +-{ +- gchar **package_ids; +- +- /* TODO: add more code here */ +- switch (event) { +- case PM_TRANS_EVT_REMOVE_START: +- pk_backend_set_allow_cancel (backend_instance, FALSE); +- +- /* reset transaction subprogress */ +- trans_subprogress = -1; +- +- emit_package (backend_instance, data1, ALPM_LOCAL_DB_ALIAS, PK_INFO_ENUM_REMOVING); +- break; +- case PM_TRANS_EVT_ADD_START: +- pk_backend_set_allow_cancel (backend_instance, FALSE); +- +- /* reset transaction subprogress */ +- trans_subprogress = -1; +- +- pk_backend_set_status (backend_instance, PK_STATUS_ENUM_INSTALL); +- +- package_ids = pk_backend_get_strv (backend_instance, "package_ids"); +- if (package_ids != NULL) { +- unsigned int iterator; +- +- /* search for package in package_ids */ +- gchar *package_id_needle = pkg_to_package_id_str (data1, ""); +- +- g_debug ("needle is %s", package_id_needle); +- for (iterator = 0; iterator < g_strv_length (package_ids); ++iterator) +- if (strstr (package_ids[iterator], package_id_needle) != NULL) { +- pk_backend_package (backend_instance, PK_INFO_ENUM_INSTALLING, package_ids[iterator], alpm_pkg_get_desc (data1)); +- break; +- } +- +- g_free (package_id_needle); +- } else +- /* we are installing a local file */ +- emit_package (backend_instance, data1, "local", PK_INFO_ENUM_INSTALLING); +- +- break; +- case PM_TRANS_EVT_UPGRADE_START: +- pk_backend_set_allow_cancel (backend_instance, FALSE); +- +- /* reset transaction subprogress */ +- trans_subprogress = -1; +- +- emit_package (backend_instance, data1, ALPM_LOCAL_DB_ALIAS, PK_INFO_ENUM_UPDATING); +- break; +- default: g_debug ("alpm: event %i happened", event); +- } +-} +- +-static void +-cb_trans_conv (pmtransconv_t conv, void *data1, void *data2, void *data3, int *response) +-{ +- /* TODO: check if some code needs to be placed there */ +-} +- +-static void +-cb_trans_progress (pmtransprog_t event, const char *pkgname, int percent, int howmany, int current) ++gchar * ++pk_backend_get_description (PkBackend *self) + { +- if (trans_subprogress != percent) { +- /* avoid duplicates */ +- trans_subprogress = percent; ++ g_return_val_if_fail (self != NULL, NULL); + +- if (event == PM_TRANS_PROGRESS_ADD_START || event == PM_TRANS_PROGRESS_UPGRADE_START || event == PM_TRANS_PROGRESS_REMOVE_START) { +- int trans_percent; +- +- g_debug ("alpm: transaction percentage for %s is %i", pkgname, percent); +- trans_percent = (int) ((float) ((current - 1) * 100 + percent)) / ((float) (howmany * 100)) * 100; +- pk_backend_set_sub_percentage ((PkBackend *) backend_instance, percent); +- pk_backend_set_percentage ((PkBackend *) backend_instance, trans_percent); +- } +- } ++ return g_strdup ("alpm"); + } + +-static void +-cb_dl_progress (const char *filename, off_t file_xfered, off_t file_total) ++gchar * ++pk_backend_get_author (PkBackend *self) + { +- int file_percent; +- int trans_percent; +- +- if (g_str_has_suffix (filename, ALPM_PKG_EXT)) { +- if (g_strcmp0 (filename, current_file) != 0) { +- alpm_list_t *repos; +- alpm_list_t *packages; +- pmpkg_t *current_pkg = NULL; +- const gchar *repo_name = NULL; +- +- g_free (current_file); +- current_file = g_strdup (filename); +- +- /* iterate repos */ +- for (repos = alpm_option_get_syncdbs (); current_pkg == NULL && repos; repos = alpm_list_next (repos)) { +- pmdb_t *db = alpm_list_getdata (repos); +- +- /* iterate pkgs */ +- for (packages = alpm_db_get_pkgcache (db); current_pkg == NULL && packages; packages = alpm_list_next (packages)) { +- pmpkg_t *pkg = alpm_list_getdata (packages); +- +- /* compare package information with file name */ +- gchar *needle = g_strjoin ("-", alpm_pkg_get_name (pkg), alpm_pkg_get_version (pkg), NULL); +- if (needle != NULL && strcmp (needle, "") != 0) +- g_debug ("matching %s with %s", filename, needle); +- if (g_str_has_prefix (filename, needle)) { +- current_pkg = pkg; +- repo_name = alpm_db_get_name (db); +- } +- g_free (needle); +- } +- } +- +- if (current_pkg != NULL) +- emit_package (backend_instance, current_pkg, repo_name, PK_INFO_ENUM_DOWNLOADING); +- } +- } ++ g_return_val_if_fail (self != NULL, NULL); + +- file_percent = (int) ((float) file_xfered) / ((float) file_total) * 100; +- trans_percent = (int) ((float) (trans_xfered + file_xfered)) / ((float) trans_total) * 100; +- pk_backend_set_sub_percentage ((PkBackend *) backend_instance, file_percent); +- pk_backend_set_percentage ((PkBackend *) backend_instance, trans_percent); +- +- if (file_xfered == file_total) { +- downloaded_files = alpm_list_add (downloaded_files, g_strdup (filename)); +- trans_xfered = trans_xfered + file_total; +- } ++ return g_strdup ("Jonathan Conder "); + } + +-static void +-cb_dl_total (off_t total) +-{ +- trans_total = total; +- /* zero total size means that download is finished, so clear trans_xfered */ +- if (total == 0) +- trans_xfered = 0; +-} +- +-/** +- * strtrim: +- * Trim whitespaces and newlines from a string +- */ +-static char * +-strtrim (char *str) +-{ +- char *pch = str; +- +- if (str == NULL || *str == '\0') +- /* string is empty, so we're done. */ +- return (str); +- +- while (isspace (*pch)) +- pch++; +- +- if (pch != str) +- memmove (str, pch, (strlen (pch) + 1)); +- +- /* check if there wasn't anything but whitespace in the string. */ +- if (*str == '\0') +- return (str); +- +- pch = (str + (strlen (str) - 1)); +- +- while (isspace (*pch)) +- pch--; +- +- *++pch = '\0'; +- +- return (str); +-} +- +-/** +- * _strnadd: +- * Helper function for strreplace +- */ +-static void +-_strnadd (char **str, const char *append, unsigned int count) +-{ +- if (*str) +- *str = realloc (*str, strlen (*str) + count + 1); +- else +- *str = calloc (sizeof (char), count + 1); +- +- strncat (*str, append, count); +-} +- +-/** +- * strreplace: +- * Replace all occurences of 'needle' with 'replace' in 'str', returning +- * a new string (must be free'd) +- */ +-static char * +-strreplace (const char *str, const char *needle, const char *replace) +-{ +- const char *p, *q; +- char *newstr = NULL; +- unsigned int needlesz = strlen (needle), replacesz = strlen (replace); +- +- p = q = str; +- +- while (1) { +- q = strstr (p, needle); +- if (!q) { +- /* not found */ +- if (*p) /* add the rest of 'p' */ +- _strnadd (&newstr, p, strlen (p)); +- +- break; +- } else { /* found match */ +- if (q > p) /* add chars between this occurance and last occurance, if any */ +- _strnadd (&newstr, p, q - p); +- +- _strnadd (&newstr, replace, replacesz); +- p = q + needlesz; +- } +- } +- +- return newstr; +-} +- +-/** +- * set_repeating_option: +- * Add repeating options such as NoExtract, NoUpgrade, etc to alpm settings. +- * @param ptr a pointer to the start of the multiple options +- * @param option the string (friendly) name of the option, used for messages +- * @param optionfunc a function pointer to an alpm_option_add_* function +- */ +-static void +-set_repeating_option (const char *ptr, const char *option, void (*optionfunc) (const char*)) +-{ +- char *p = (char*) ptr; +- char *q; +- +- while ((q = strchr (p, ' '))) { +- *q = '\0'; +- (*optionfunc) (p); +- g_debug ("config: %s: %s", option, p); +- p = q; +- p++; +- } +- (*optionfunc) (p); +- g_debug ("config: %s: %s", option, p); +-} +- +-/** +- * option_add_syncfirst: +- * Add package name to SyncFirst list +- * @param name name of the package to be added +- */ +-static void +-option_add_syncfirst (const char *name) { +- syncfirst = alpm_list_add (syncfirst, strdup (name)); +-} +- +-/** +- * option_add_holdpkg: +- * Add package name to HoldPkg list +- * @param name name of the package to be added +- */ +-static void +-option_add_holdpkg (const char *name) { +- holdpkg = alpm_list_add (holdpkg, strdup (name)); +-} +- +-/** +- * parse_config: +- * Parse config file and set all the needed options +- * Based heavily on the pacman source code +- * @param file full name of config file +- * @param givensection section to start from +- * @param givendb db to start from +- */ +-static int +-parse_config (const char *file, const char *givensection, pmdb_t * const givendb) +-{ +- FILE *fp = NULL; +- char line[PATH_MAX + 1]; +- int linenum = 0; +- char *ptr, *section = NULL; +- pmdb_t *db = NULL; +- +- /* set default options */ +- alpm_option_set_root (ALPM_ROOT); +- alpm_option_set_dbpath (ALPM_DBPATH); +- alpm_option_add_cachedir (ALPM_CACHEDIR); +- alpm_option_set_logfile (ALPM_LOGFILE); +- +- fp = fopen (file, "r"); +- if (fp == NULL) { +- g_error ("config file %s could not be read", file); +- return 1; +- } +- +- /* if we are passed a section, use it as our starting point */ +- if (givensection != NULL) +- section = strdup (givensection); +- +- /* if we are passed a db, use it as our starting point */ +- if (givendb != NULL) +- db = givendb; +- +- while (fgets (line, PATH_MAX, fp)) { +- linenum++; +- strtrim (line); +- +- if (strlen (line) == 0 || line[0] == '#') +- continue; +- +- if ((ptr = strchr (line, '#'))) +- *ptr = '\0'; +- +- if (line[0] == '[' && line[strlen (line) - 1] == ']') { +- /* new config section, skip the '[' */ +- ptr = line; +- ptr++; +- if (section) +- free (section); +- +- section = strdup (ptr); +- section[strlen (section) - 1] = '\0'; +- g_debug ("config: new section '%s'", section); +- if (!strlen (section)) { +- g_debug ("config file %s, line %d: bad section name", file, linenum); +- return 1; +- } +- +- /* if we are not looking at the options section, register a db */ +- if (g_strcmp0 (section, "options") != 0) +- db = alpm_db_register_sync (section); +- } else { +- /* directive */ +- char *key; +- key = line; +- ptr = line; +- /* strsep modifies the 'line' string: 'key \0 ptr' */ +- strsep (&ptr, "="); +- strtrim (key); +- strtrim (ptr); +- +- if (key == NULL) { +- g_error ("config file %s, line %d: syntax error in config file - missing key.", file, linenum); +- return 1; +- } +- if (section == NULL) { +- g_error ("config file %s, line %d: all directives must belong to a section.", file, linenum); +- return 1; +- } +- +- if (ptr == NULL && g_strcmp0 (section, "options") == 0) { +- /* directives without settings, all in [options] */ +- if (g_strcmp0 (key, "UseSyslog") == 0) { +- alpm_option_set_usesyslog (1); +- g_debug ("config: usesyslog"); +- } else if (g_strcmp0 (key, "UseDelta") == 0) { +- alpm_option_set_usedelta (1); +- g_debug ("config: usedelta"); +- } else if (g_strcmp0 (key, "ILoveCandy") != 0 && g_strcmp0 (key, "ShowSize") != 0 && g_strcmp0 (key, "TotalDownload") != 0 && g_strcmp0 (key, "NoPassiveFTP") != 0) { +- g_warning ("config file %s, line %d: directive '%s' not recognized.", file, linenum, key); +- } +- } else { +- /* directives with settings */ +- if (g_strcmp0 (key, "Include") == 0) { +- g_debug ("config: including %s", ptr); +- parse_config (ptr, section, db); +- /* Ignore include failures... assume non-critical */ +- } else if (g_strcmp0 (section, "options") == 0) { +- if (g_strcmp0 (key, "NoUpgrade") == 0) { +- set_repeating_option (ptr, "NoUpgrade", alpm_option_add_noupgrade); +- } else if (g_strcmp0 (key, "NoExtract") == 0) { +- set_repeating_option (ptr, "NoExtract", alpm_option_add_noextract); +- } else if (g_strcmp0 (key, "IgnorePkg") == 0) { +- set_repeating_option (ptr, "IgnorePkg", alpm_option_add_ignorepkg); +- } else if (g_strcmp0 (key, "IgnoreGroup") == 0) { +- set_repeating_option (ptr, "IgnoreGroup", alpm_option_add_ignoregrp); +- } else if (g_strcmp0 (key, "HoldPkg") == 0) { +- set_repeating_option (ptr, "HoldPkg", option_add_holdpkg); +- } else if (g_strcmp0 (key, "SyncFirst") == 0) { +- set_repeating_option (ptr, "SyncFirst", option_add_syncfirst); +- } else if (g_strcmp0 (key, "DBPath") == 0) { +- alpm_option_set_dbpath (ptr); +- } else if (g_strcmp0 (key, "CacheDir") == 0) { +- if (alpm_option_add_cachedir (ptr) != 0) { +- g_error ("problem adding cachedir '%s' (%s)", ptr, alpm_strerrorlast ()); +- return 1; +- } +- g_debug ("config: cachedir: %s", ptr); +- } else if (g_strcmp0 (key, "RootDir") == 0) { +- alpm_option_set_root (ptr); +- g_debug ("config: rootdir: %s", ptr); +- } else if (g_strcmp0 (key, "LogFile") == 0) { +- alpm_option_set_logfile (ptr); +- g_debug ("config: logfile: %s", ptr); +- } else if (g_strcmp0 (key, "XferCommand") != 0 && g_strcmp0 (key, "CleanMethod") != 0) { +- g_warning ("config file %s, line %d: directive '%s' not recognized.", file, linenum, key); +- } +- } else if (g_strcmp0 (key, "Server") == 0) { +- /* let's attempt a replacement for the current repo */ +- char *server = strreplace (ptr, "$repo", section); +- +- if (alpm_db_setserver (db, server) != 0) { +- /* pm_errno is set by alpm_db_setserver */ +- g_error ("config file %s, line %d: could not add server URL to database (%s).", file, linenum, alpm_strerrorlast ()); +- free (server); +- return 1; +- } +- free (server); +- } else { +- g_warning ("config file %s, line %d: directive '%s' not recognized.", file, linenum, key); +- } +- } +- } +- } +- +- fclose (fp); +- if (section) +- free (section); +- +- g_debug ("config: finished parsing %s", file); +- return 0; +-} +- +-/** +- * backend_initialize: +- */ +-static void +-backend_initialize (PkBackend *backend) +-{ +- /* initialize backend_instance for use in callback functions */ +- backend_instance = backend; +- +- g_debug ("alpm: initializing backend"); +- +- if (alpm_initialize () == -1) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_FAILED_INITIALIZATION, "Failed to initialize package manager"); +- g_debug ("alpm: %s", alpm_strerror (pm_errno)); +- return; +- } +- +- /* read options from config file */ +- if (parse_config (ALPM_CONFIG_PATH, NULL, NULL) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_FAILED_CONFIG_PARSING, "Failed to parse config file"); +- alpm_release (); +- return; +- } +- +- if (alpm_db_register_local () == NULL) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_AVAILABLE, "Failed to load local database"); +- g_debug ("alpm: %s", alpm_strerror (pm_errno)); +- alpm_release (); +- return; +- } +- +- alpm_option_set_dlcb (cb_dl_progress); +- alpm_option_set_totaldlcb (cb_dl_total); +- +- /* fill in group mapping */ +- group_map = g_hash_table_new (g_str_hash, g_str_equal); +- g_hash_table_insert (group_map, (gchar *) "gnome", (gchar *) "desktop-gnome"); +- g_hash_table_insert (group_map, (gchar *) "gnome-extra", (gchar *) "desktop-gnome"); +- g_hash_table_insert (group_map, (gchar *) "compiz-gnome", (gchar *) "desktop-gnome"); +- g_hash_table_insert (group_map, (gchar *) "kde", (gchar *) "desktop-kde"); +- g_hash_table_insert (group_map, (gchar *) "compiz-kde", (gchar *) "desktop-kde"); +- g_hash_table_insert (group_map, (gchar *) "compiz-fusion-kde", (gchar *) "desktop-kde"); +- g_hash_table_insert (group_map, (gchar *) "lxde", (gchar *) "desktop-other"); +- g_hash_table_insert (group_map, (gchar *) "rox-desktop", (gchar *) "desktop-other"); +- g_hash_table_insert (group_map, (gchar *) "e17-cvs", (gchar *) "desktop-other"); +- g_hash_table_insert (group_map, (gchar *) "e17-extra-cvs", (gchar *) "desktop-other"); +- g_hash_table_insert (group_map, (gchar *) "e17-libs-cvs", (gchar *) "desktop-other"); +- g_hash_table_insert (group_map, (gchar *) "xfce4", (gchar *) "desktop-xfce"); +- g_hash_table_insert (group_map, (gchar *) "xfce4-goodies", (gchar *) "desktop-xfce"); +- g_hash_table_insert (group_map, (gchar *) "bmp-io-plugins", (gchar *) "multimedia"); +- g_hash_table_insert (group_map, (gchar *) "bmp-plugins", (gchar *) "multimedia"); +- g_hash_table_insert (group_map, (gchar *) "bmp-visualization-plugins", (gchar *) "multimedia"); +- g_hash_table_insert (group_map, (gchar *) "gstreamer0.10-plugins", (gchar *) "multimedia"); +- g_hash_table_insert (group_map, (gchar *) "ladspa-plugins", (gchar *) "multimedia"); +- g_hash_table_insert (group_map, (gchar *) "pvr", (gchar *) "multimedia"); +- g_hash_table_insert (group_map, (gchar *) "mythtv-extras", (gchar *) "multimedia"); +- g_hash_table_insert (group_map, (gchar *) "xmms-effect-plugins", (gchar *) "multimedia"); +- g_hash_table_insert (group_map, (gchar *) "xmms-io-plugins", (gchar *) "multimedia"); +- g_hash_table_insert (group_map, (gchar *) "xmms-plugins", (gchar *) "multimedia"); +- g_hash_table_insert (group_map, (gchar *) "base-devel", (gchar *) "programming"); +- g_hash_table_insert (group_map, (gchar *) "texlive-lang", (gchar *) "publishing"); +- g_hash_table_insert (group_map, (gchar *) "texlive-lang-doc", (gchar *) "publishing"); +- g_hash_table_insert (group_map, (gchar *) "texlive-most", (gchar *) "publishing"); +- g_hash_table_insert (group_map, (gchar *) "texlive-most-doc", (gchar *) "publishing"); +- g_hash_table_insert (group_map, (gchar *) "texlive-most-svn", (gchar *) "publishing"); +- g_hash_table_insert (group_map, (gchar *) "base", (gchar *) "system"); +- +- g_debug ("alpm: ready to go"); +-} +- +-/** +- * backend_destroy: +- */ +-static void +-backend_destroy (PkBackend *backend) +-{ +- g_hash_table_destroy (group_map); +- +- if (alpm_release () == -1) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_FAILED_FINALISE, "Failed to release package manager"); +- g_debug ("alpm: %s", alpm_strerror (pm_errno)); +- } +-} +- +-/** +- * backend_get_groups: +- */ +-static PkBitfield +-backend_get_groups (PkBackend *backend) +-{ +- return pk_bitfield_from_enums ( +- PK_GROUP_ENUM_DESKTOP_GNOME, +- PK_GROUP_ENUM_DESKTOP_KDE, +- PK_GROUP_ENUM_DESKTOP_OTHER, +- PK_GROUP_ENUM_DESKTOP_XFCE, +- PK_GROUP_ENUM_MULTIMEDIA, +- PK_GROUP_ENUM_OTHER, +- PK_GROUP_ENUM_PROGRAMMING, +- PK_GROUP_ENUM_PUBLISHING, +- PK_GROUP_ENUM_SYSTEM, +- -1); +-} +- +-/** +- * backend_get_filters: +- */ +-static PkBitfield +-backend_get_filters (PkBackend *backend) +-{ +- return pk_bitfield_from_enums (PK_FILTER_ENUM_INSTALLED, -1); +-} +- +-/** +- * backend_get_mime_types: +- */ +-static gchar * +-backend_get_mime_types (PkBackend *backend) +-{ +- return g_strdup ("application/x-compressed-tar"); +-} +- +-/** +- * backend_cancel: +- **/ +-static void +-backend_cancel (PkBackend *backend) +-{ +- pk_backend_set_status (backend, PK_STATUS_ENUM_CANCEL); +-} +- +-/** +- * backend_download_packages_thread: +- */ + static gboolean +-backend_download_packages_thread (PkBackend *backend) ++pk_backend_spawn (PkBackend *self, const gchar *command) + { +- gchar **package_ids = pk_backend_get_strv (backend, "package_ids"); +- const gchar *directory = pk_backend_get_string (backend, "directory"); +- unsigned int iterator; +- alpm_list_t *list_iterator; +- alpm_list_t *cachedirs = NULL; +- alpm_list_t *data = NULL; +- +- g_debug ("alpm: downloading packages to %s", directory); +- +- /* old cachedirs list automatically gets freed in alpm, so make a copy */ +- for (list_iterator = alpm_option_get_cachedirs (); list_iterator; list_iterator = alpm_list_next (list_iterator)) +- cachedirs = alpm_list_add (cachedirs, g_strdup (alpm_list_getdata (list_iterator))); +- /* set new download destination */ +- alpm_option_set_cachedirs (NULL); +- alpm_option_add_cachedir (directory); +- +- /* create a new transaction */ +- if (alpm_trans_init (PM_TRANS_FLAG_NODEPS | PM_TRANS_FLAG_DOWNLOADONLY, cb_trans_evt, cb_trans_conv, cb_trans_progress) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- pk_backend_finished (backend); +- return FALSE; +- } ++ int status; ++ GError *error = NULL; + +- /* add targets to the transaction */ +- for (iterator = 0; iterator < g_strv_length (package_ids); ++iterator) { +- gchar **package_id_data = pk_package_id_split (package_ids[iterator]); +- +- if (alpm_sync_target (package_id_data[PK_PACKAGE_ID_NAME]) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- alpm_trans_release (); +- pk_backend_finished (backend); +- return FALSE; +- } ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (command != NULL, FALSE); + +- g_strfreev (package_id_data); ++ if (!g_spawn_command_line_sync (command, NULL, NULL, &status, &error)) { ++ g_warning ("could not spawn command: %s", error->message); ++ g_error_free (error); ++ return FALSE; + } + +- /* prepare and commit transaction */ +- if (alpm_trans_prepare (&data) != 0 || alpm_trans_commit (&data) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- alpm_trans_release (); +- pk_backend_finished (backend); ++ if (WIFEXITED (status) == 0) { ++ g_warning ("command did not execute correctly"); + return FALSE; + } + +- alpm_trans_release (); +- +- /* emit downloaded packages */ +- for (list_iterator = downloaded_files; list_iterator; list_iterator = alpm_list_next (list_iterator)) { +- gchar *package_id = NULL; +- gchar *filename; +- +- /* TODO: optimize this? split-then-join isn't good */ +- for (iterator = 0; package_id == NULL && iterator < g_strv_length (package_ids); ++iterator) { +- gchar **package_id_data = pk_package_id_split (package_ids[iterator]); +- gchar *needle = g_strjoin ("-", package_id_data[PK_PACKAGE_ID_NAME], package_id_data[PK_PACKAGE_ID_VERSION], NULL); +- +- if (needle != NULL && strcmp (needle, "") != 0) +- g_debug ("matching %s with %s", (char *) alpm_list_getdata (list_iterator), needle); +- if (g_str_has_prefix ((char *) alpm_list_getdata (list_iterator), needle)) +- package_id = package_ids[iterator]; +- +- g_free (needle); +- g_strfreev (package_id_data); +- } +- +- filename = g_build_filename (directory, alpm_list_getdata (list_iterator), NULL); +- pk_backend_files (backend, package_id, filename); +- g_free (filename); +- +- /* clean up list data */ +- g_free (alpm_list_getdata (list_iterator)); ++ if (WEXITSTATUS (status) != EXIT_SUCCESS) { ++ gint code = WEXITSTATUS (status); ++ g_warning ("command returned error code %d", code); ++ return FALSE; + } +- alpm_list_free (downloaded_files); + +- /* return cachedirs back */ +- alpm_option_set_cachedirs (cachedirs); +- +- pk_backend_finished (backend); + return TRUE; + } + +-/** +- * backend_download_packages: +- */ +-static void +-backend_download_packages (PkBackend *backend, gchar **package_ids, const gchar *directory) +-{ +- pk_backend_set_status (backend, PK_STATUS_ENUM_DOWNLOAD); +- pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); +- +- pk_backend_thread_create (backend, backend_download_packages_thread); +-} +- +-/** +- * backend_get_depends: +- */ +-static void +-backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids, gboolean recursive) ++gint ++pk_backend_fetchcb (const gchar *url, const gchar *path, gint force) + { +- unsigned int iterator; ++ GRegex *xo, *xi; ++ gchar *oldpwd, *basename, *file, *part; ++ gchar *tempcmd = NULL, *finalcmd = NULL; ++ gint result = 0; + +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_set_allow_cancel (backend, FALSE); ++ g_return_val_if_fail (url != NULL, -1); ++ g_return_val_if_fail (path != NULL, -1); ++ g_return_val_if_fail (xfercmd != NULL, -1); ++ g_return_val_if_fail (backend != NULL, -1); + +- for (iterator = 0; iterator < g_strv_length (package_ids); ++iterator) { +- alpm_list_t *list_iterator; +- +- pmpkg_t *pkg = pkg_from_package_id (package_ids[iterator]); +- if (pkg == NULL) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, alpm_strerrorlast ()); +- pk_backend_finished (backend); +- return; +- } +- +- for (list_iterator = alpm_pkg_get_depends (pkg); list_iterator; list_iterator = alpm_list_next (list_iterator)) { +- pmdepend_t *dep = alpm_list_getdata (list_iterator); +- pmpkg_t *dep_pkg; +- gboolean found = FALSE; +- +- if (!pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED)) { +- /* search in sync dbs */ +- alpm_list_t *db_iterator; +- for (db_iterator = alpm_option_get_syncdbs (); found == FALSE && db_iterator; db_iterator = alpm_list_next (db_iterator)) { +- pmdb_t *syncdb = alpm_list_getdata (db_iterator); +- +- g_debug ("alpm: searching for %s in %s", alpm_dep_get_name (dep), alpm_db_get_name (syncdb)); +- +- dep_pkg = alpm_db_get_pkg (syncdb, alpm_dep_get_name (dep)); +- if (dep_pkg && alpm_depcmp (dep_pkg, dep) && pkg_cmp (dep_pkg, alpm_db_get_pkg (alpm_option_get_localdb (), alpm_dep_get_name (dep))) != 0) { +- found = TRUE; +- emit_package (backend, dep_pkg, alpm_db_get_name (syncdb), PK_INFO_ENUM_AVAILABLE); +- } +- } +- } +- +- if (!pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED)) { +- g_debug ("alpm: searching for %s in local db", alpm_dep_get_name (dep)); +- +- /* search in local db */ +- dep_pkg = alpm_db_get_pkg (alpm_option_get_localdb (), alpm_dep_get_name (dep)); +- if (dep_pkg && alpm_depcmp (dep_pkg, dep)) { +- found = TRUE; +- emit_package (backend, dep_pkg, ALPM_LOCAL_DB_ALIAS, PK_INFO_ENUM_INSTALLED); +- } +- } +- } ++ oldpwd = g_get_current_dir (); ++ if (g_chdir (path) < 0) { ++ g_warning ("could not find or read directory %s", path); ++ g_free (oldpwd); ++ return -1; + } + +- pk_backend_finished (backend); +-} +- +-/** +- * backend_get_details: +- */ +-static void +-backend_get_details (PkBackend *backend, gchar **package_ids) +-{ +- unsigned int iterator; +- +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_set_allow_cancel (backend, FALSE); +- +- for (iterator = 0; iterator < g_strv_length (package_ids); ++iterator) { +- alpm_list_t *licenses_list; +- GString *licenses_str; +- gchar *licenses; +- +- pmpkg_t *pkg = pkg_from_package_id (package_ids[iterator]); +- if (pkg == NULL) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, alpm_strerrorlast ()); +- pk_backend_finished (backend); +- return; +- } +- +- licenses_list = alpm_pkg_get_licenses (pkg); +- if (licenses_list == NULL) +- licenses_str = g_string_new ("unknown"); +- else { +- alpm_list_t *list_iterator; +- +- licenses_str = g_string_new (""); +- for (list_iterator = licenses_list; list_iterator; list_iterator = alpm_list_next (list_iterator)) { +- if (list_iterator != licenses_list) +- g_string_append (licenses_str, ", "); +- g_string_append (licenses_str, (char *) alpm_list_getdata (list_iterator)); +- } +- } +- +- /* get licenses_str content to licenses array */ +- licenses = g_string_free (licenses_str, FALSE); ++ xo = g_regex_new ("%o", 0, 0, NULL); ++ xi = g_regex_new ("%u", 0, 0, NULL); + +- /* return details */ +- pk_backend_details (backend, package_ids[iterator], licenses, PK_GROUP_ENUM_OTHER, alpm_pkg_get_desc (pkg), alpm_pkg_get_url (pkg), alpm_pkg_get_size (pkg)); ++ basename = g_path_get_basename (url); ++ file = g_strconcat (path, basename, NULL); ++ part = g_strconcat (file, ".part", NULL); + +- /* free licenses array as we no longer need it */ +- g_free (licenses); ++ if (force != 0 && g_file_test (part, G_FILE_TEST_EXISTS)) { ++ g_unlink (part); + } +- +- pk_backend_finished (backend); +-} +- +-/** +- * backend_get_files: +- */ +-static void +-backend_get_files (PkBackend *backend, gchar **package_ids) +-{ +- unsigned int iterator; +- +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_set_allow_cancel (backend, FALSE); +- +- for (iterator = 0; iterator < g_strv_length (package_ids); ++iterator) { +- alpm_list_t *files_list; +- GString *files_str; +- gchar *files; +- +- pmpkg_t *pkg = pkg_from_package_id (package_ids[iterator]); +- if (pkg == NULL) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, alpm_strerrorlast ()); +- pk_backend_finished (backend); +- return; +- } +- +- files_list = alpm_pkg_get_files (pkg); +- files_str = g_string_new (""); +- if (files_list != NULL) { +- alpm_list_t *list_iterator; +- +- for (list_iterator = files_list; list_iterator; list_iterator = alpm_list_next (list_iterator)) { +- if (list_iterator != files_list) +- g_string_append (files_str, ";"); +- g_string_append (files_str, alpm_option_get_root ()); +- g_string_append (files_str, (char *) alpm_list_getdata (list_iterator)); +- } +- } +- files = g_string_free (files_str, FALSE); +- +- pk_backend_files (backend, package_ids[iterator], files); ++ if (force != 0 && g_file_test (file, G_FILE_TEST_EXISTS)) { ++ g_unlink (file); + } + +- pk_backend_finished (backend); +-} +- +-static void +-backend_search (PkBackend *backend, pmdb_t *repo, const gchar *needle, PkAlpmSearchType search_type) { +- /* package cache */ +- alpm_list_t *pkg_cache; +- +- /* utility variables */ +- alpm_list_t *iterator; +- const gchar *repo_name; +- PkInfoEnum info; +- gboolean match; +- gboolean repo_is_local; +- +- if (repo == alpm_option_get_localdb ()) { +- repo_name = ALPM_LOCAL_DB_ALIAS; +- info = PK_INFO_ENUM_INSTALLED; +- repo_is_local = TRUE; +- } else { +- repo_name = alpm_db_get_name (repo); +- info = PK_INFO_ENUM_AVAILABLE; +- repo_is_local = FALSE; ++ tempcmd = g_regex_replace_literal (xo, xfercmd, -1, 0, part, 0, NULL); ++ if (tempcmd == NULL) { ++ result = -1; ++ goto out; + } + +- /* get package cache for specified repo */ +- pkg_cache = alpm_db_get_pkgcache (repo); +- +- /* iterate package cache */ +- for (iterator = pkg_cache; iterator; iterator = alpm_list_next (iterator)) { +- pmpkg_t *pkg = alpm_list_getdata (iterator); +- +- switch (search_type) { +- alpm_list_t *provides; +- alpm_list_t *groups; +- +- case PK_ALPM_SEARCH_TYPE_NULL: +- match = TRUE; +- break; +- case PK_ALPM_SEARCH_TYPE_RESOLVE: +- match = g_strcmp0 (alpm_pkg_get_name (pkg), needle) == 0; +- break; +- case PK_ALPM_SEARCH_TYPE_NAME: +- match = strstr (alpm_pkg_get_name (pkg), needle) != NULL; +- break; +- case PK_ALPM_SEARCH_TYPE_DETAILS: +- /* workaround for buggy packages with no description */ +- if (alpm_pkg_get_desc (pkg) == NULL) +- match = FALSE; +- else +- /* TODO: strcasestr is a non-standard extension, replace it? */ +- match = strcasestr (alpm_pkg_get_desc (pkg), needle) != NULL; +- break; +- case PK_ALPM_SEARCH_TYPE_GROUP: +- match = FALSE; +- /* iterate groups */ +- for (groups = alpm_pkg_get_groups (pkg); groups && !match; groups = alpm_list_next (groups)) { +- gchar *group = (gchar *) g_hash_table_lookup (group_map, (char *) alpm_list_getdata (groups)); +- if (group == NULL) +- group = (gchar *) "other"; +- match = (g_strcmp0 (group, needle) == 0); +- } +- break; +- case PK_ALPM_SEARCH_TYPE_PROVIDES: +- match = FALSE; +- /* iterate provides */ +- for (provides = alpm_pkg_get_provides (pkg); provides && !match; provides = alpm_list_next (provides)) +- match = (g_strcmp0 (needle, alpm_list_getdata (provides)) == 0); +- break; +- default: +- match = FALSE; +- } ++ finalcmd = g_regex_replace_literal (xi, tempcmd, -1, 0, url, 0, NULL); ++ if (finalcmd == NULL) { ++ result = -1; ++ goto out; ++ } + +- if (match && (repo_is_local || pkg_cmp (pkg, alpm_db_get_pkg (alpm_option_get_localdb (), alpm_pkg_get_name (pkg))) != 0)) { +- /* we found what we wanted */ +- emit_package (backend, pkg, repo_name, info); ++ if (!pk_backend_spawn (backend, finalcmd)) { ++ result = -1; ++ goto out; ++ } else if (g_strrstr (xfercmd, "%o") != NULL) { ++ /* using .part filename */ ++ if (g_rename (part, file) < 0) { ++ g_warning ("could not rename %s", part); ++ result = -1; ++ goto out; + } + } +-} + +-/** +- * backend_search_values: +- */ +-static void +-backend_search_values (PkBackend *backend, pmdb_t *repo, gchar **values, PkAlpmSearchType search_type) { +- unsigned int iterator; ++out: ++ g_free (finalcmd); ++ g_free (tempcmd); + +- for (iterator = 0; iterator < g_strv_length (values); ++iterator) +- backend_search (backend, repo, values[iterator], search_type); +-} +- +-/** +- * backend_get_packages_thread: +- */ +-static gboolean +-backend_get_packages_thread (PkBackend *backend) +-{ +- PkBitfield filters = pk_backend_get_uint (backend, "filters"); +- +- gboolean search_installed = pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED); +- gboolean search_not_installed = pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED); ++ g_free (part); ++ g_free (file); ++ g_free (basename); + +- if (!search_not_installed) { +- /* search in local db */ +- backend_search (backend, alpm_option_get_localdb (), NULL, PK_ALPM_SEARCH_TYPE_NULL); +- } +- +- if (!search_installed) { +- /* search in sync repos */ +- alpm_list_t *repos; +- /* iterate repos */ +- for (repos = alpm_option_get_syncdbs (); repos; repos = alpm_list_next (repos)) +- backend_search (backend, alpm_list_getdata (repos), NULL, PK_ALPM_SEARCH_TYPE_NULL); +- } ++ g_regex_unref (xi); ++ g_regex_unref (xo); + +- pk_backend_finished (backend); +- return TRUE; +-} ++ g_chdir (oldpwd); ++ g_free (oldpwd); + +-/** +- * backend_get_packages: +- */ +-static void +-backend_get_packages (PkBackend *backend, PkBitfield filters) +-{ +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); +- +- pk_backend_thread_create (backend, backend_get_packages_thread); ++ return result; + } + +-/** +- * backend_get_repo_list: +- */ + static void +-backend_get_repo_list (PkBackend *backend, PkBitfield filters) ++pk_backend_logcb (pmloglevel_t level, const gchar *format, va_list args) + { +- alpm_list_t *list_iterator; +- +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); ++ gchar *output; + +- /* iterate on repo list */ +- for (list_iterator = alpm_option_get_syncdbs (); list_iterator; list_iterator = alpm_list_next (list_iterator)) { +- pmdb_t *db = alpm_list_getdata (list_iterator); ++ g_return_if_fail (backend != NULL); + +- pk_backend_repo_detail (backend, alpm_db_get_name (db), alpm_db_get_name (db), TRUE); ++ if (format != NULL && format[0] != '\0') { ++ output = g_strdup_vprintf (format, args); ++ } else { ++ return; + } + +- pk_backend_finished (backend); +-} +- +-/** +- * backend_get_update_detail: +- */ +-static void +-backend_get_update_detail (PkBackend *backend, gchar **package_ids) +-{ +- unsigned int iterator; +- +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_set_allow_cancel (backend, FALSE); +- +- for (iterator = 0; iterator < g_strv_length (package_ids); ++iterator) { +- /* TODO: add changelog code here */ +- gchar **package_id_data = pk_package_id_split (package_ids[iterator]); +- +- pmpkg_t *installed_pkg = alpm_db_get_pkg (alpm_option_get_localdb (), package_id_data[PK_PACKAGE_ID_NAME]); ++ /* report important output to PackageKit */ ++ switch (level) { ++ case PM_LOG_DEBUG: ++ case PM_LOG_FUNCTION: ++ g_debug ("%s", output); ++ break; + +- gchar *installed_package_id = installed_pkg ? pkg_to_package_id_str (installed_pkg, ALPM_LOCAL_DB_ALIAS) : NULL; +- pk_backend_update_detail (backend, package_ids[iterator], installed_package_id, "", "", "", "", PK_RESTART_ENUM_NONE, +- installed_pkg ? "Update to latest available version" : "Install as a dependency for another update", +- NULL, PK_UPDATE_STATE_ENUM_UNKNOWN, NULL, NULL); +- g_free (installed_package_id); ++ case PM_LOG_WARNING: ++ g_warning ("%s", output); ++ pk_backend_output (backend, output); ++ break; + +- g_strfreev (package_id_data); ++ default: ++ g_warning ("%s", output); ++ break; + } + +- pk_backend_finished (backend); ++ g_free (output); + } + +-/** +- * backend_get_updates: +- */ +-static void +-backend_get_updates (PkBackend *backend, PkBitfield filters) ++static gboolean ++pk_backend_initialize_alpm (PkBackend *self, GError **error) + { +- alpm_list_t *list_iterator; +- +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_set_allow_cancel (backend, FALSE); +- +- /* iterate through list of installed packages to find update for each */ +- for (list_iterator = alpm_db_get_pkgcache (alpm_option_get_localdb ()); list_iterator; list_iterator = alpm_list_next (list_iterator)) { +- alpm_list_t *db_iterator; +- +- pmpkg_t *pkg = alpm_list_getdata (list_iterator); ++ struct utsname un; ++ gchar *user_agent; + +- for (db_iterator = alpm_option_get_syncdbs (); db_iterator; db_iterator = alpm_list_next (db_iterator)) { +- pmdb_t *db = alpm_list_getdata (db_iterator); +- pmpkg_t *repo_pkg = alpm_db_get_pkg (db, alpm_pkg_get_name (pkg)); ++ g_return_val_if_fail (self != NULL, FALSE); + +- if (repo_pkg != NULL && alpm_pkg_vercmp (alpm_pkg_get_version (pkg), alpm_pkg_get_version (repo_pkg)) < 0) { +- gchar *package_id_str = pkg_to_package_id_str (repo_pkg, alpm_db_get_name (db)); +- pk_backend_package (backend, PK_INFO_ENUM_NORMAL, package_id_str, alpm_pkg_get_desc (repo_pkg)); +- g_free (package_id_str); ++ /* PATH might have been nuked by D-Bus */ ++ g_setenv ("PATH", PK_BACKEND_DEFAULT_PATH, FALSE); + +- break; +- } +- } +- } +- +- pk_backend_finished (backend); +-} ++ uname (&un); ++ user_agent = g_strdup_printf ("%s/%s (%s %s) libalpm/%s", ++ PACKAGE_TARNAME, PACKAGE_VERSION, ++ un.sysname, un.machine, alpm_version ()); ++ g_setenv ("HTTP_USER_AGENT", user_agent, FALSE); ++ g_free (user_agent); + +-/** +- * backend_install_files_thread: +- */ +-static gboolean +-backend_install_files_thread (PkBackend *backend) +-{ +- unsigned int iterator; +- alpm_list_t *data = NULL; +- +- gchar **full_paths = pk_backend_get_strv (backend, "full_paths"); +- +- /* create a new transaction */ +- if (alpm_trans_init (0, cb_trans_evt, cb_trans_conv, cb_trans_progress) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- pk_backend_finished (backend); ++ g_debug ("initializing"); ++ if (alpm_initialize () < 0) { ++ g_set_error_literal (error, ALPM_ERROR, pm_errno, ++ alpm_strerrorlast ()); + return FALSE; + } + +- /* add targets to the transaction */ +- for (iterator = 0; iterator < g_strv_length (full_paths); ++iterator) { +- if (alpm_add_target (full_paths[iterator]) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- alpm_trans_release (); +- pk_backend_finished (backend); +- return FALSE; +- } else +- g_debug ("alpm: %s added to transaction queue", full_paths[iterator]); +- } +- +- /* prepare and commit transaction */ +- if (alpm_trans_prepare (&data) != 0 || alpm_trans_commit (&data) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- alpm_trans_release (); +- pk_backend_finished (backend); +- return FALSE; ++ backend = self; ++ localdb = alpm_option_get_localdb (); ++ if (localdb == NULL) { ++ g_set_error (error, ALPM_ERROR, pm_errno, "[%s]: %s", "local", ++ alpm_strerrorlast ()); + } + +- alpm_trans_release (); ++ /* set some sane defaults */ ++ alpm_option_set_logcb (pk_backend_logcb); ++ alpm_option_set_root (PK_BACKEND_DEFAULT_ROOT); ++ alpm_option_set_dbpath (PK_BACKEND_DEFAULT_DBPATH); ++ alpm_option_set_logfile (PK_BACKEND_DEFAULT_LOGFILE); + +- pk_backend_finished (backend); + return TRUE; + } + +-/** +- * backend_install_files: +- */ + static void +-backend_install_files (PkBackend *backend, gboolean only_trusted, gchar **full_paths) +-{ +- pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL); +- pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); +- +- pk_backend_thread_create (backend, backend_install_files_thread); +-} +- +-/** +- * backend_install_packages_thread: +- */ +-static gboolean +-backend_install_packages_thread (PkBackend *backend) ++pk_backend_destroy_alpm (PkBackend *self) + { +- unsigned int iterator; +- alpm_list_t *data = NULL; +- +- /* FIXME: support only_trusted */ +- gchar **package_ids = pk_backend_get_strv (backend, "package_ids"); +- +- /* create a new transaction */ +- if (alpm_trans_init (0, cb_trans_evt, cb_trans_conv, cb_trans_progress) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- pk_backend_finished (backend); +- return FALSE; +- } +- +- /* add targets to the transaction */ +- for (iterator = 0; iterator < g_strv_length (package_ids); ++iterator) { +- gchar **package_id_data = pk_package_id_split (package_ids[iterator]); ++ g_return_if_fail (self != NULL); + +- if (alpm_sync_target (package_id_data[PK_PACKAGE_ID_NAME]) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); ++ if (backend != NULL) { ++ if (alpm_trans_get_flags () != -1) { + alpm_trans_release (); +- pk_backend_finished (backend); +- return FALSE; + } +- +- g_strfreev (package_id_data); +- } +- +- /* prepare and commit transaction */ +- if (alpm_trans_prepare (&data) != 0 || alpm_trans_commit (&data) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- alpm_trans_release (); +- pk_backend_finished (backend); +- return FALSE; ++ alpm_release (); ++ backend = NULL; + } + +- alpm_trans_release (); +- +- pk_backend_finished (backend); +- return TRUE; +-} +- +-/** +- * backend_install_packages: +- */ +-static void +-backend_install_packages (PkBackend *backend, gboolean only_trusted, gchar **package_ids) +-{ +- pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); +- +- pk_backend_thread_create (backend, backend_install_packages_thread); ++ FREELIST (syncfirsts); ++ FREELIST (holdpkgs); ++ g_free (xfercmd); + } + +-/** +- * backend_refresh_cache_thread: +- */ +-static gboolean +-backend_refresh_cache_thread (PkBackend *backend) ++void ++pk_backend_initialize (PkBackend *self) + { +- alpm_list_t *list_iterator; ++ GError *error = NULL; + +- if (alpm_trans_init (PM_TRANS_FLAG_NOSCRIPTLET, cb_trans_evt, cb_trans_conv, cb_trans_progress) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- pk_backend_finished (backend); +- return FALSE; +- } ++ g_return_if_fail (self != NULL); + +- for (list_iterator = alpm_option_get_syncdbs (); list_iterator; list_iterator = alpm_list_next (list_iterator)) { +- pmdb_t *db = (pmdb_t *) alpm_list_getdata (list_iterator); +- if (alpm_db_update (FALSE, db) == -1) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- pk_backend_finished (backend); +- return FALSE; +- } ++ if (!pk_backend_initialize_alpm (self, &error) || ++ !pk_backend_initialize_databases (self, &error) || ++ !pk_backend_initialize_groups (self, &error)) { ++ g_error ("%s", error->message); ++ g_error_free (error); + } +- +- alpm_trans_release (); +- +- pk_backend_finished (backend); +- return TRUE; + } + +-/** +- * backend_refresh_cache: +- */ +-static void +-backend_refresh_cache (PkBackend *backend, gboolean force) ++void ++pk_backend_destroy (PkBackend *self) + { +- if (!pk_backend_is_online (backend)) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Can not refresh cache in offline mode"); +- pk_backend_finished (backend); +- return; +- } +- +- pk_backend_set_status (backend, PK_STATUS_ENUM_REFRESH_CACHE); +- pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); ++ g_return_if_fail (self != NULL); + +- pk_backend_thread_create (backend, backend_refresh_cache_thread); ++ pk_backend_destroy_groups (self); ++ pk_backend_destroy_databases (self); ++ pk_backend_destroy_alpm (self); + } + +-/** +- * backend_remove_packages_thread: +- */ +-static gboolean +-backend_remove_packages_thread (PkBackend *backend) ++PkBitfield ++pk_backend_get_filters (PkBackend *self) + { +- unsigned int iterator; +- alpm_list_t *list_iterator = NULL; +- alpm_list_t *data = NULL; +- gchar *holdpkgs = NULL; +- +- gchar **package_ids = pk_backend_get_strv (backend, "package_ids"); +- gboolean allow_deps = pk_backend_get_bool (backend, "allow_deps"); +- gboolean autoremove = pk_backend_get_bool (backend, "autoremove"); +- +- pmtransflag_t flags = 0; +- if (allow_deps) +- flags |= PM_TRANS_FLAG_CASCADE; +- if (autoremove) +- flags |= PM_TRANS_FLAG_RECURSE; +- +- /* create a new transaction */ +- if (alpm_trans_init (flags, cb_trans_evt, cb_trans_conv, cb_trans_progress) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- pk_backend_finished (backend); +- return FALSE; +- } +- +- /* add targets to the transaction */ +- for (iterator = 0; iterator < g_strv_length (package_ids); ++iterator) { +- gchar **package_id_data = pk_package_id_split (package_ids[iterator]); +- +- if (alpm_remove_target (package_id_data[PK_PACKAGE_ID_NAME]) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- alpm_trans_release (); +- pk_backend_finished (backend); +- return FALSE; +- } +- +- g_strfreev (package_id_data); +- } +- +- /* prepare transaction */ +- if (alpm_trans_prepare (&data) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- alpm_trans_release (); +- pk_backend_finished (backend); +- return FALSE; +- } ++ g_return_val_if_fail (self != NULL, 0); + +- /* search for HoldPkg's in target list */ +- for (list_iterator = alpm_trans_get_remove (); list_iterator; list_iterator = alpm_list_next (list_iterator)) { +- pmpkg_t *pkg = alpm_list_getdata (list_iterator); +- const gchar *pkgname = alpm_pkg_get_name (pkg); +- +- if (alpm_list_find_str (holdpkg, pkgname) != NULL) { +- if (holdpkgs == NULL) +- holdpkgs = g_strdup (pkgname); +- else { +- gchar *new_holdpkgs = g_strdup_printf ("%s, %s", holdpkgs, pkgname); +- g_free (holdpkgs); +- holdpkgs = new_holdpkgs; +- } +- } +- } +- +- /* pacman just asks for confirmation, but here we fail to be safe */ +- if (holdpkgs != NULL) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE, "The following packages are designated HoldPkg: %s", holdpkgs); +- free (holdpkgs); +- alpm_trans_release (); +- pk_backend_finished (backend); +- return FALSE; +- } +- +- /* commit transaction */ +- if (alpm_trans_commit (&data) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- alpm_trans_release (); +- pk_backend_finished (backend); +- return FALSE; +- } +- +- alpm_trans_release (); +- +- pk_backend_finished (backend); +- return TRUE; ++ return pk_bitfield_from_enums (PK_FILTER_ENUM_INSTALLED, -1); + } + +-/** +- * backend_remove_packages: +- */ +-static void +-backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove) ++gchar * ++pk_backend_get_mime_types (PkBackend *self) + { +- pk_backend_set_status (backend, PK_STATUS_ENUM_REMOVE); +- pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); ++ g_return_val_if_fail (self != NULL, NULL); + +- pk_backend_thread_create (backend, backend_remove_packages_thread); ++ /* packages currently use .pkg.tar.gz and .pkg.tar.xz */ ++ return g_strdup ("application/x-compressed-tar;" ++ "application/x-xz-compressed-tar"); + } + +-/** +- * backend_resolve_thread: +- */ +-static gboolean +-backend_resolve_thread (PkBackend *backend) ++void ++pk_backend_run (PkBackend *self, PkStatusEnum status, PkBackendThreadFunc func) + { +- unsigned int iterator; +- +- gchar **package_ids = pk_backend_get_strv (backend, "package_ids"); +- PkBitfield filters = pk_backend_get_uint (backend, "filters"); +- +- gboolean search_installed = pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED); +- gboolean search_not_installed = pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED); +- +- for (iterator = 0; iterator < g_strv_length (package_ids); ++iterator) { +- if (pk_package_id_check (package_ids[iterator])) { +- /* skip all the db iterations and so on - we already know everything */ +- pmpkg_t *pkg = pkg_from_package_id (package_ids[iterator]); +- +- if (pkg != NULL) { +- gchar **package_id_data = pk_package_id_split (package_ids[iterator]); +- +- if (!search_not_installed && g_strcmp0 (package_id_data[PK_PACKAGE_ID_DATA], ALPM_LOCAL_DB_ALIAS) == 0) +- emit_package (backend, pkg, ALPM_LOCAL_DB_ALIAS, PK_INFO_ENUM_INSTALLED); +- +- if (!search_installed && g_strcmp0 (package_id_data[PK_PACKAGE_ID_DATA], ALPM_LOCAL_DB_ALIAS) != 0) +- emit_package (backend, pkg, package_id_data[PK_PACKAGE_ID_DATA], PK_INFO_ENUM_INSTALLED); +- +- g_strfreev (package_id_data); +- } +- } else { +- /* good old way with backend_search */ +- /* TODO: check, is it still needed? */ +- if (!search_not_installed) { +- /* search in local db */ +- backend_search (backend, alpm_option_get_localdb (), package_ids[iterator], PK_ALPM_SEARCH_TYPE_RESOLVE); +- } +- +- if (!search_installed) { +- /* search in sync repos */ +- alpm_list_t *repos; +- /* iterate repos */ +- for (repos = alpm_option_get_syncdbs (); repos; repos = alpm_list_next (repos)) +- backend_search (backend, alpm_list_getdata (repos), package_ids[iterator], PK_ALPM_SEARCH_TYPE_RESOLVE); +- } +- } ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (func != NULL); ++ ++ g_static_mutex_lock (&mutex); ++ ++ if (cancellable != NULL) { ++ g_warning ("cancellable was not NULL"); ++ g_object_unref (cancellable); + } ++ cancellable = g_cancellable_new (); + +- pk_backend_finished (backend); +- return TRUE; +-} ++ g_static_mutex_unlock (&mutex); + +-/** +- * backend_resolve: +- */ +-static void +-backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids) +-{ +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); ++ pk_backend_set_allow_cancel (self, TRUE); + +- pk_backend_thread_create (backend, backend_resolve_thread); ++ pk_backend_set_status (self, status); ++ pk_backend_thread_create (self, func); + } + +-/** +- * backend_search_thread: +- */ +-static gboolean +-backend_search_thread (PkBackend *backend) ++void ++pk_backend_cancel (PkBackend *self) + { +- gchar **values = pk_backend_get_strv (backend, "values"); +- PkBitfield filters = pk_backend_get_uint (backend, "filters"); +- PkAlpmSearchType search_type = pk_backend_get_uint (backend, "search-type"); +- +- gboolean search_installed = pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED); +- gboolean search_not_installed = pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED); ++ g_return_if_fail (self != NULL); + +- if (!search_not_installed) { +- /* search in local db */ +- backend_search_values (backend, alpm_option_get_localdb (), values, search_type); +- } ++ g_static_mutex_lock (&mutex); + +- if (!search_installed) { +- /* search in sync repos */ +- alpm_list_t *repos; +- /* iterate repos */ +- for (repos = alpm_option_get_syncdbs (); repos; repos = alpm_list_next (repos)) +- backend_search_values (backend, alpm_list_getdata (repos), values, search_type); ++ if (cancellable != NULL) { ++ g_cancellable_cancel (cancellable); + } + +- pk_backend_finished (backend); +- return TRUE; ++ g_static_mutex_unlock (&mutex); + } + +-/** +- * backend_search_details: +- */ +-static void +-backend_search_details (PkBackend *backend, PkBitfield filters, gchar **values) ++gboolean ++pk_backend_cancelled (PkBackend *self) + { +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); +- pk_backend_set_uint (backend, "search-type", PK_ALPM_SEARCH_TYPE_DETAILS); +- pk_backend_set_strv (backend, "values", values); ++ gboolean cancelled; + +- pk_backend_thread_create (backend, backend_search_thread); +-} ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (cancellable != NULL, FALSE); + +-/** +- * backend_search_groups: +- */ +-static void +-backend_search_groups (PkBackend *backend, PkBitfield filters, gchar **values) +-{ +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); +- pk_backend_set_uint (backend, "search-type", PK_ALPM_SEARCH_TYPE_GROUP); +- pk_backend_set_strv (backend, "values", values); ++ g_static_mutex_lock (&mutex); + +- pk_backend_thread_create (backend, backend_search_thread); +-} ++ cancelled = g_cancellable_is_cancelled (cancellable); + +-/** +- * backend_search_names: +- */ +-static void +-backend_search_names (PkBackend *backend, PkBitfield filters, gchar **values) +-{ +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); +- pk_backend_set_uint (backend, "search-type", PK_ALPM_SEARCH_TYPE_NAME); +- pk_backend_set_strv (backend, "values", values); ++ g_static_mutex_unlock (&mutex); + +- pk_backend_thread_create (backend, backend_search_thread); ++ return cancelled; + } + +-/** +- * backend_update_packages: +- */ +-static void +-backend_update_packages (PkBackend *backend, gboolean only_trusted, gchar **package_ids) ++gboolean ++pk_backend_finish (PkBackend *self, GError *error) + { +- pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); ++ gboolean cancelled = FALSE; + +- pk_backend_thread_create (backend, backend_install_packages_thread); +-} ++ g_return_val_if_fail (self != NULL, FALSE); + +-/** +- * backend_update_system_thread: +- */ +-static gboolean +-backend_update_system_thread (PkBackend *backend) +-{ +- alpm_list_t *data = NULL; +- +- /* FIXME: support only_trusted */ ++ pk_backend_set_allow_cancel (self, FALSE); + +- /* create a new transaction */ +- if (alpm_trans_init (0, cb_trans_evt, cb_trans_conv, cb_trans_progress) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- pk_backend_finished (backend); +- return FALSE; +- } ++ g_static_mutex_lock (&mutex); + +- /* set action, prepare and commit transaction */ +- if (alpm_sync_sysupgrade (FALSE) != 0 || alpm_trans_prepare (&data) != 0 || alpm_trans_commit (&data) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerrorlast ()); +- alpm_trans_release (); +- pk_backend_finished (backend); +- return FALSE; ++ if (cancellable != NULL) { ++ cancelled = g_cancellable_is_cancelled (cancellable); ++ g_object_unref (cancellable); ++ cancellable = NULL; + } + +- alpm_trans_release (); ++ g_static_mutex_unlock (&mutex); + +- pk_backend_finished (backend); +- return TRUE; +-} +- +-/** +- * backend_update_system: +- */ +-static void +-backend_update_system (PkBackend *backend, gboolean only_trusted) +-{ +- pk_backend_thread_create (backend, backend_update_system_thread); +-} ++ if (error != NULL) { ++ pk_backend_error (self, error); ++ g_error_free (error); ++ } + +-/** +- * backend_what_provides: +- */ +-static void +-backend_what_provides (PkBackend *backend, PkBitfield filters, PkProvidesEnum provides, gchar **values) +-{ +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); +- pk_backend_set_uint (backend, "search-type", PK_ALPM_SEARCH_TYPE_PROVIDES); +- pk_backend_set_strv (backend, "values", values); ++ if (cancelled) { ++ pk_backend_set_status (self, PK_STATUS_ENUM_CANCEL); ++ } + +- pk_backend_thread_create (backend, backend_search_thread); ++ pk_backend_thread_finished (self); ++ return (error == NULL); + } +- +-/* FIXME: port this away from PK_BACKEND_OPTIONS */ +-PK_BACKEND_OPTIONS ( +- "alpm", /* description */ +- "Valeriy Lyasotskiy ", /* author */ +- backend_initialize, /* initialize */ +- backend_destroy, /* destroy */ +- backend_get_groups, /* get_groups */ +- backend_get_filters, /* get_filters */ +- NULL, /* get_roles */ +- backend_get_mime_types, /* get_mime_types */ +- backend_cancel, /* cancel */ +- backend_download_packages, /* download_packages */ +- NULL, /* get_categories */ +- backend_get_depends, /* get_depends */ +- backend_get_details, /* get_details */ +- NULL, /* get_distro_upgrades */ +- backend_get_files, /* get_files */ +- backend_get_packages, /* get_packages */ +- backend_get_repo_list, /* get_repo_list */ +- NULL, /* get_requires */ +- backend_get_update_detail, /* get_update_detail */ +- backend_get_updates, /* get_updates */ +- backend_install_files, /* install_files */ +- backend_install_packages, /* install_packages */ +- NULL, /* install_signature */ +- backend_refresh_cache, /* refresh_cache */ +- backend_remove_packages, /* remove_packages */ +- NULL, /* repo_enable */ +- NULL, /* repo_set_data */ +- backend_resolve, /* resolve */ +- NULL, /* rollback */ +- backend_search_details, /* search_details */ +- NULL, /* search_files */ +- backend_search_groups, /* search_groups */ +- backend_search_names, /* search_names */ +- backend_update_packages, /* update_packages */ +- backend_update_system, /* update_system */ +- backend_what_provides, /* what_provides */ +- NULL, /* simulate_install_files */ +- NULL, /* simulate_install_packages */ +- NULL, /* simulate_remove_packages */ +- NULL, /* simulate_update_packages */ +- NULL, /* upgrade_system */ +- NULL, /* transaction_start */ +- NULL /* transaction_stop */ +-); +diff --git a/backends/alpm/pk-backend-alpm.h b/backends/alpm/pk-backend-alpm.h +new file mode 100644 +index 0000000..23a2724 +--- /dev/null ++++ b/backends/alpm/pk-backend-alpm.h +@@ -0,0 +1,47 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++#include ++ ++extern PkBackend *backend; ++extern GCancellable *cancellable; ++ ++extern pmdb_t *localdb; ++ ++extern gchar *xfercmd; ++extern alpm_list_t *holdpkgs; ++extern alpm_list_t *syncfirsts; ++ ++gint pk_backend_fetchcb (const gchar *url, const gchar *path, ++ gint force); ++ ++void pk_backend_run (PkBackend *self, PkStatusEnum status, ++ PkBackendThreadFunc func); ++ ++void pk_backend_cancel (PkBackend *self); ++ ++gboolean pk_backend_cancelled (PkBackend *self); ++ ++gboolean pk_backend_finish (PkBackend *self, GError *error); +diff --git a/backends/alpm/pk-backend-config.c b/backends/alpm/pk-backend-config.c +new file mode 100644 +index 0000000..21a4c54 +--- /dev/null ++++ b/backends/alpm/pk-backend-config.c +@@ -0,0 +1,775 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "pk-backend-alpm.h" ++#include "pk-backend-config.h" ++#include "pk-backend-error.h" ++ ++typedef struct { ++ gboolean checkspace, ilovecandy, showsize, totaldl, usedelta, usesyslog; ++ ++ gchar *arch, *cleanmethod, *dbpath, *logfile, *root, *xfercmd; ++ ++ alpm_list_t *cachedirs, *holdpkgs, *ignoregrps, *ignorepkgs, ++ *noextracts, *noupgrades, *syncfirsts; ++ ++ alpm_list_t *repos; ++ GHashTable *servers; ++ GRegex *xrepo, *xarch; ++} PkBackendConfig; ++ ++static PkBackendConfig * ++pk_backend_config_new (void) ++{ ++ PkBackendConfig *config = g_new0 (PkBackendConfig, 1); ++ config->servers = g_hash_table_new_full (g_str_hash, g_str_equal, ++ g_free, NULL); ++ config->xrepo = g_regex_new ("\\$repo", 0, 0, NULL); ++ config->xarch = g_regex_new ("\\$arch", 0, 0, NULL); ++ return config; ++} ++ ++static void ++pk_backend_config_list_free (alpm_list_t *list) ++{ ++ alpm_list_free_inner (list, g_free); ++ alpm_list_free (list); ++} ++ ++static gboolean ++pk_backend_config_servers_free (gpointer repo, gpointer list, gpointer data) ++{ ++ pk_backend_config_list_free ((alpm_list_t *) list); ++ return TRUE; ++} ++ ++static void ++pk_backend_config_free (PkBackendConfig *config) ++{ ++ g_return_if_fail (config != NULL); ++ ++ g_free (config->arch); ++ g_free (config->cleanmethod); ++ g_free (config->dbpath); ++ g_free (config->logfile); ++ g_free (config->root); ++ g_free (config->xfercmd); ++ ++ FREELIST (config->cachedirs); ++ FREELIST (config->holdpkgs); ++ FREELIST (config->ignoregrps); ++ FREELIST (config->ignorepkgs); ++ FREELIST (config->noextracts); ++ FREELIST (config->noupgrades); ++ FREELIST (config->syncfirsts); ++ ++ pk_backend_config_list_free (config->repos); ++ g_hash_table_foreach_remove (config->servers, ++ pk_backend_config_servers_free, NULL); ++ g_hash_table_unref (config->servers); ++ g_regex_unref (config->xrepo); ++ g_regex_unref (config->xarch); ++} ++ ++static void ++pk_backend_config_set_checkspace (PkBackendConfig *config) ++{ ++ g_return_if_fail (config != NULL); ++ ++ config->checkspace = TRUE; ++} ++ ++static void ++pk_backend_config_set_ilovecandy (PkBackendConfig *config) ++{ ++ g_return_if_fail (config != NULL); ++ ++ config->ilovecandy = TRUE; ++} ++ ++static void ++pk_backend_config_set_showsize (PkBackendConfig *config) ++{ ++ g_return_if_fail (config != NULL); ++ ++ config->showsize = TRUE; ++} ++ ++static void ++pk_backend_config_set_totaldl (PkBackendConfig *config) ++{ ++ g_return_if_fail (config != NULL); ++ ++ config->totaldl = TRUE; ++} ++ ++static void ++pk_backend_config_set_usedelta (PkBackendConfig *config) ++{ ++ g_return_if_fail (config != NULL); ++ ++ config->usedelta = TRUE; ++} ++ ++static void ++pk_backend_config_set_usesyslog (PkBackendConfig *config) ++{ ++ g_return_if_fail (config != NULL); ++ ++ config->usesyslog = TRUE; ++} ++ ++typedef struct { ++ const gchar *name; ++ void (*func) (PkBackendConfig *config); ++} PkBackendConfigBoolean; ++ ++/* keep this in alphabetical order */ ++static const PkBackendConfigBoolean pk_backend_config_boolean_options[] = { ++ { "CheckSpace", pk_backend_config_set_checkspace }, ++ { "ILoveCandy", pk_backend_config_set_ilovecandy }, ++ { "ShowSize", pk_backend_config_set_showsize }, ++ { "TotalDownload", pk_backend_config_set_totaldl }, ++ { "UseDelta", pk_backend_config_set_usedelta }, ++ { "UseSyslog", pk_backend_config_set_usesyslog }, ++ { NULL, NULL } ++}; ++ ++static gboolean ++pk_backend_config_set_boolean (PkBackendConfig *config, const gchar *option) ++{ ++ gsize i; ++ ++ g_return_val_if_fail (config != NULL, FALSE); ++ g_return_val_if_fail (option != NULL, FALSE); ++ ++ for (i = 0;; ++i) { ++ const gchar *name = pk_backend_config_boolean_options[i].name; ++ gint cmp = g_strcmp0 (option, name); ++ ++ if (name == NULL || cmp < 0) { ++ return FALSE; ++ } else if (cmp == 0) { ++ pk_backend_config_boolean_options[i].func (config); ++ return TRUE; ++ } ++ } ++} ++ ++static void ++pk_backend_config_add_cachedir (PkBackendConfig *config, const gchar *path) ++{ ++ gsize length; ++ gchar *cachedir; ++ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (path != NULL); ++ ++ /* allocate normally */ ++ length = strlen (path) + 1; ++ cachedir = malloc (length * sizeof (gchar)); ++ g_strlcpy (cachedir, path, length); ++ config->cachedirs = alpm_list_add (config->cachedirs, cachedir); ++} ++ ++static void ++pk_backend_config_set_arch (PkBackendConfig *config, const gchar *arch) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (arch != NULL); ++ ++ g_free (config->arch); ++ if (g_strcmp0 (arch, "auto") == 0) { ++ struct utsname un; ++ uname (&un); ++ config->arch = g_strdup (un.machine); ++ } else { ++ config->arch = g_strdup (arch); ++ } ++} ++ ++static void ++pk_backend_config_set_cleanmethod (PkBackendConfig *config, const gchar *method) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (method != NULL); ++ ++ g_free (config->cleanmethod); ++ config->cleanmethod = g_strdup (method); ++} ++ ++static void ++pk_backend_config_set_dbpath (PkBackendConfig *config, const gchar *path) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (path != NULL); ++ ++ g_free (config->dbpath); ++ config->dbpath = g_strdup (path); ++} ++ ++static void ++pk_backend_config_set_logfile (PkBackendConfig *config, const gchar *filename) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (filename != NULL); ++ ++ g_free (config->logfile); ++ config->logfile = g_strdup (filename); ++} ++ ++static void ++pk_backend_config_set_root (PkBackendConfig *config, const gchar *path) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (path != NULL); ++ ++ g_free (config->root); ++ config->root = g_strdup (path); ++} ++ ++static void ++pk_backend_config_set_xfercmd (PkBackendConfig *config, const gchar *command) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (command != NULL); ++ ++ g_free (config->xfercmd); ++ config->xfercmd = g_strdup (command); ++} ++ ++typedef struct { ++ const gchar *name; ++ void (*func) (PkBackendConfig *config, const gchar *s); ++} PkBackendConfigString; ++ ++/* keep this in alphabetical order */ ++static const PkBackendConfigString pk_backend_config_string_options[] = { ++ { "Architecture", pk_backend_config_set_arch }, ++ { "CacheDir", pk_backend_config_add_cachedir }, ++ { "CleanMethod", pk_backend_config_set_cleanmethod }, ++ { "DBPath", pk_backend_config_set_dbpath }, ++ { "LogFile", pk_backend_config_set_logfile }, ++ { "RootDir", pk_backend_config_set_root }, ++ { "XferCommand", pk_backend_config_set_xfercmd }, ++ { NULL, NULL } ++}; ++ ++static gboolean ++pk_backend_config_set_string (PkBackendConfig *config, const gchar *option, ++ const gchar *s) ++{ ++ gsize i; ++ ++ g_return_val_if_fail (config != NULL, FALSE); ++ g_return_val_if_fail (option != NULL, FALSE); ++ g_return_val_if_fail (s != NULL, FALSE); ++ ++ for (i = 0;; ++i) { ++ const gchar *name = pk_backend_config_string_options[i].name; ++ gint cmp = g_strcmp0 (option, name); ++ ++ if (name == NULL || cmp < 0) { ++ return FALSE; ++ } else if (cmp == 0) { ++ pk_backend_config_string_options[i].func (config, s); ++ return TRUE; ++ } ++ } ++} ++ ++static void ++pk_backend_config_add_holdpkg (PkBackendConfig *config, gchar *package) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (package != NULL); ++ ++ config->holdpkgs = alpm_list_add (config->holdpkgs, package); ++} ++ ++static void ++pk_backend_config_add_ignoregrp (PkBackendConfig *config, gchar *group) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (group != NULL); ++ ++ config->ignoregrps = alpm_list_add (config->ignoregrps, group); ++} ++ ++static void ++pk_backend_config_add_ignorepkg (PkBackendConfig *config, gchar *package) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (package != NULL); ++ ++ config->ignorepkgs = alpm_list_add (config->ignorepkgs, package); ++} ++ ++static void ++pk_backend_config_add_noextract (PkBackendConfig *config, gchar *filename) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (filename != NULL); ++ ++ config->noextracts = alpm_list_add (config->noextracts, filename); ++} ++ ++static void ++pk_backend_config_add_noupgrade (PkBackendConfig *config, gchar *filename) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (filename != NULL); ++ ++ config->noupgrades = alpm_list_add (config->noupgrades, filename); ++} ++ ++static void ++pk_backend_config_add_syncfirst (PkBackendConfig *config, gchar *package) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (package != NULL); ++ ++ config->syncfirsts = alpm_list_add (config->syncfirsts, package); ++} ++ ++typedef struct { ++ const gchar *name; ++ void (*func) (PkBackendConfig *config, gchar *value); ++} PkBackendConfigList; ++ ++/* keep this in alphabetical order */ ++static const PkBackendConfigList pk_backend_config_list_options[] = { ++ { "HoldPkg", pk_backend_config_add_holdpkg }, ++ { "IgnoreGroup", pk_backend_config_add_ignoregrp }, ++ { "IgnorePkg", pk_backend_config_add_ignorepkg }, ++ { "NoExtract", pk_backend_config_add_noextract }, ++ { "NoUpgrade", pk_backend_config_add_noupgrade }, ++ { "SyncFirst", pk_backend_config_add_syncfirst }, ++ { NULL, NULL } ++}; ++ ++static void ++pk_backend_config_list_add (PkBackendConfig *config, gsize option, ++ const gchar *list) ++{ ++ gchar *str; ++ ++ for (str = strchr (list, ' '); str != NULL; str = strchr (list, ' ')) { ++ /* allocate normally */ ++ gchar *value = malloc ((++str - list) * sizeof (gchar)); ++ g_strlcpy (value, list, str - list); ++ pk_backend_config_list_options[option].func (config, value); ++ list = str; ++ } ++ pk_backend_config_list_options[option].func (config, strdup (list)); ++} ++ ++static gboolean ++pk_backend_config_set_list (PkBackendConfig *config, const gchar *option, ++ const gchar *list) ++{ ++ gsize i; ++ ++ g_return_val_if_fail (config != NULL, FALSE); ++ g_return_val_if_fail (option != NULL, FALSE); ++ g_return_val_if_fail (list != NULL, FALSE); ++ ++ for (i = 0;; ++i) { ++ const gchar *name = pk_backend_config_list_options[i].name; ++ gint cmp = g_strcmp0 (option, name); ++ ++ if (name == NULL || cmp < 0) { ++ return FALSE; ++ } else if (cmp == 0) { ++ pk_backend_config_list_add (config, i, list); ++ return TRUE; ++ } ++ } ++} ++ ++static void ++pk_backend_config_add_repo (PkBackendConfig *config, const gchar *repo) ++{ ++ g_return_if_fail (config != NULL); ++ g_return_if_fail (repo != NULL); ++ ++ if (alpm_list_find_str (config->repos, repo) == NULL) { ++ config->repos = alpm_list_add (config->repos, g_strdup (repo)); ++ } ++} ++ ++static gboolean ++pk_backend_config_repo_add_server (PkBackendConfig *config, const gchar *repo, ++ const gchar *value, GError **e) ++{ ++ alpm_list_t *list; ++ gchar *url; ++ ++ g_return_val_if_fail (config != NULL, FALSE); ++ g_return_val_if_fail (repo != NULL, FALSE); ++ g_return_val_if_fail (alpm_list_find_str (config->repos, repo) != NULL, ++ FALSE); ++ g_return_val_if_fail (value != NULL, FALSE); ++ ++ url = g_regex_replace_literal (config->xrepo, value, -1, 0, repo, 0, e); ++ if (url == NULL) { ++ return FALSE; ++ } ++ ++ if (config->arch != NULL) { ++ gchar *temp = url; ++ url = g_regex_replace_literal (config->xarch, temp, -1, 0, ++ config->arch, 0, e); ++ g_free (temp); ++ ++ if (url == NULL) { ++ return FALSE; ++ } ++ } else if (strstr (url, "$arch") != NULL) { ++ g_set_error (e, ALPM_ERROR, PM_ERR_CONFIG_INVALID, ++ "url contained $arch, which is not set"); ++ } ++ ++ list = (alpm_list_t *) g_hash_table_lookup (config->servers, repo); ++ list = alpm_list_add (list, url); ++ g_hash_table_insert (config->servers, g_strdup (repo), list); ++ ++ return TRUE; ++} ++ ++static gboolean ++pk_backend_config_parse (PkBackendConfig *config, const gchar *filename, ++ gchar *section, GError **error) ++{ ++ GFile *file; ++ GFileInputStream *is; ++ GDataInputStream *input; ++ ++ gchar *key, *str, *line = NULL; ++ guint num = 1; ++ ++ GError *e = NULL; ++ ++ g_return_val_if_fail (config != NULL, FALSE); ++ g_return_val_if_fail (filename != NULL, FALSE); ++ ++ file = g_file_new_for_path (filename); ++ is = g_file_read (file, NULL, &e); ++ ++ if (is == NULL) { ++ g_propagate_error (error, e); ++ g_object_unref (file); ++ return FALSE; ++ } ++ ++ input = g_data_input_stream_new (G_INPUT_STREAM (is)); ++ section = g_strdup (section); ++ ++ for (;; g_free (line), ++num) { ++ line = g_data_input_stream_read_line (input, NULL, NULL, &e); ++ ++ if (line != NULL) { ++ g_strstrip (line); ++ } else { ++ break; ++ } ++ ++ /* skip empty lines */ ++ if (*line == '\0' || *line == '#') { ++ continue; ++ } ++ ++ /* remove trailing comments */ ++ for (str = line; *str != '\0' && *str != '#'; ++str); ++ *str-- = '\0'; ++ ++ /* change sections */ ++ if (*line == '[' && *str == ']') { ++ *str = '\0'; ++ str = line + 1; ++ ++ if (*str == '\0') { ++ g_set_error (&e, ALPM_ERROR, ++ PM_ERR_CONFIG_INVALID, ++ "empty section name"); ++ break; ++ } ++ ++ g_free (section); ++ section = g_strdup (str); ++ ++ if (g_strcmp0 (section, "options") != 0) { ++ pk_backend_config_add_repo (config, section); ++ } ++ ++ continue; ++ } ++ ++ /* parse a directive */ ++ if (section == NULL) { ++ g_set_error (&e, ALPM_ERROR, PM_ERR_CONFIG_INVALID, ++ "directive must belong to a section"); ++ break; ++ } ++ ++ str = line; ++ key = strsep (&str, "="); ++ g_strchomp (key); ++ if (str != NULL) { ++ g_strchug (str); ++ } ++ ++ if (str == NULL) { ++ /* set a boolean directive */ ++ if (g_strcmp0 (section, "options") == 0 && ++ pk_backend_config_set_boolean (config, key)) { ++ continue; ++ } ++ /* report error below */ ++ } else if (g_strcmp0 (key, "Include") == 0) { ++ gsize i; ++ glob_t match = { 0 }; ++ ++ /* ignore globbing errors */ ++ if (glob (str, GLOB_NOCHECK, NULL, &match) != 0) { ++ continue; ++ } ++ ++ /* parse the files that matched */ ++ for (i = 0; i < match.gl_pathc; ++i) { ++ if (!pk_backend_config_parse (config, ++ match.gl_pathv[i], ++ section, &e)) { ++ break; ++ } ++ } ++ ++ globfree (&match); ++ if (e != NULL) { ++ break; ++ } else { ++ continue; ++ } ++ } else if (g_strcmp0 (section, "options") == 0) { ++ /* set a string or list directive */ ++ if (pk_backend_config_set_string (config, key, str) || ++ pk_backend_config_set_list (config, key, str)) { ++ continue; ++ } ++ /* report error below */ ++ } else if (g_strcmp0 (key, "Server") == 0) { ++ if (!pk_backend_config_repo_add_server (config, section, ++ str, &e)) { ++ break; ++ } else { ++ continue; ++ } ++ } ++ ++ /* report errors from above */ ++ g_set_error (&e, ALPM_ERROR, PM_ERR_CONFIG_INVALID, ++ "unrecognised directive '%s'", key); ++ break; ++ } ++ ++ g_free (section); ++ ++ g_object_unref (input); ++ g_object_unref (is); ++ g_object_unref (file); ++ ++ if (e != NULL) { ++ g_propagate_prefixed_error (error, e, "%s:%u", filename, num); ++ return FALSE; ++ } else { ++ return TRUE; ++ } ++} ++ ++static gboolean ++pk_backend_config_configure_paths (PkBackendConfig *config, GError **error) ++{ ++ g_return_val_if_fail (config != NULL, FALSE); ++ ++ if (config->root == NULL) { ++ config->root = g_strdup (PK_BACKEND_DEFAULT_ROOT); ++ } ++ ++ if (alpm_option_set_root (config->root) < 0) { ++ g_set_error (error, ALPM_ERROR, pm_errno, "RootDir: %s", ++ alpm_strerrorlast ()); ++ return FALSE; ++ } ++ ++ if (config->dbpath == NULL) { ++ config->dbpath = g_strconcat (alpm_option_get_root (), ++ PK_BACKEND_DEFAULT_DBPATH + 1, ++ NULL); ++ } ++ ++ if (alpm_option_set_dbpath (config->dbpath) < 0) { ++ g_set_error (error, ALPM_ERROR, pm_errno, "DBPath: %s", ++ alpm_strerrorlast ()); ++ return FALSE; ++ } ++ ++ if (config->logfile == NULL) { ++ config->logfile = g_strconcat (alpm_option_get_root (), ++ PK_BACKEND_DEFAULT_LOGFILE + 1, ++ NULL); ++ } ++ ++ alpm_option_set_logfile (config->logfile); ++ ++ if (config->cachedirs == NULL) { ++ gchar *path = g_strconcat (alpm_option_get_root (), ++ PK_BACKEND_DEFAULT_CACHEDIR + 1, ++ NULL); ++ config->cachedirs = alpm_list_add (NULL, path); ++ } ++ ++ /* alpm takes ownership */ ++ alpm_option_set_cachedirs (config->cachedirs); ++ config->cachedirs = NULL; ++ ++ return TRUE; ++} ++ ++static gboolean ++pk_backend_config_configure_repos (PkBackendConfig *config, GError **error) ++{ ++ const alpm_list_t *i; ++ ++ g_return_val_if_fail (config != NULL, FALSE); ++ ++ for (i = alpm_option_get_syncdbs (); i != NULL; i = i->next) { ++ if (alpm_db_unregister (i->data) < 0) { ++ g_set_error_literal (error, ALPM_ERROR, pm_errno, ++ alpm_strerrorlast ()); ++ return FALSE; ++ } ++ } ++ ++ for (i = config->repos; i != NULL; i = i->next) { ++ const gchar *key; ++ gpointer value; ++ pmdb_t *db; ++ alpm_list_t *j; ++ ++ key = (const gchar *) i->data; ++ value = g_hash_table_lookup (config->servers, key); ++ ++ db = alpm_db_register_sync (key); ++ if (db == NULL) { ++ g_set_error (error, ALPM_ERROR, pm_errno, "[%s]: %s", ++ key, alpm_strerrorlast ()); ++ return FALSE; ++ } ++ ++ for (j = (alpm_list_t *) value; j != NULL; j = j->next) { ++ alpm_db_setserver (db, (const gchar *) j->data); ++ } ++ } ++ ++ return TRUE; ++} ++ ++static gboolean ++pk_backend_config_configure_alpm (PkBackendConfig *config, GError **error) ++{ ++ g_return_val_if_fail (config != NULL, FALSE); ++ ++ if (!pk_backend_config_configure_paths (config, error)) { ++ return FALSE; ++ } ++ ++ alpm_option_set_checkspace (config->checkspace); ++ alpm_option_set_usedelta (config->usedelta); ++ alpm_option_set_usesyslog (config->usesyslog); ++ alpm_option_set_arch (config->arch); ++ ++ /* backend takes ownership */ ++ g_free (xfercmd); ++ xfercmd = config->xfercmd; ++ config->xfercmd = NULL; ++ ++ if (xfercmd != NULL) { ++ alpm_option_set_fetchcb (pk_backend_fetchcb); ++ } else { ++ alpm_option_set_fetchcb (NULL); ++ } ++ ++ /* backend takes ownership */ ++ FREELIST (holdpkgs); ++ holdpkgs = config->holdpkgs; ++ config->holdpkgs = NULL; ++ ++ /* backend takes ownership */ ++ FREELIST (syncfirsts); ++ syncfirsts = config->syncfirsts; ++ config->syncfirsts = NULL; ++ ++ /* alpm takes ownership */ ++ alpm_option_set_ignoregrps (config->ignoregrps); ++ config->ignoregrps = NULL; ++ ++ /* alpm takes ownership */ ++ alpm_option_set_ignorepkgs (config->ignorepkgs); ++ config->ignorepkgs = NULL; ++ ++ /* alpm takes ownership */ ++ alpm_option_set_noextracts (config->noextracts); ++ config->noextracts = NULL; ++ ++ /* alpm takes ownership */ ++ alpm_option_set_noupgrades (config->noupgrades); ++ config->noupgrades = NULL; ++ ++ if (!pk_backend_config_configure_repos (config, error)) { ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++gboolean ++pk_backend_configure (const gchar *filename, GError **error) ++{ ++ PkBackendConfig *config; ++ gboolean result; ++ ++ g_return_val_if_fail (filename != NULL, FALSE); ++ ++ config = pk_backend_config_new (); ++ ++ result = pk_backend_config_parse (config, filename, NULL, error) && ++ pk_backend_config_configure_alpm (config, error); ++ ++ pk_backend_config_free (config); ++ return result; ++} +diff --git a/backends/alpm/pk-backend-config.h b/backends/alpm/pk-backend-config.h +new file mode 100644 +index 0000000..cb8b8dc +--- /dev/null ++++ b/backends/alpm/pk-backend-config.h +@@ -0,0 +1,26 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++ ++gboolean pk_backend_configure (const gchar *filename, GError **error); +diff --git a/backends/alpm/pk-backend-databases.c b/backends/alpm/pk-backend-databases.c +new file mode 100644 +index 0000000..f6ab06e +--- /dev/null ++++ b/backends/alpm/pk-backend-databases.c +@@ -0,0 +1,346 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "pk-backend-alpm.h" ++#include "pk-backend-config.h" ++#include "pk-backend-databases.h" ++#include "pk-backend-error.h" ++ ++static GHashTable *disabled = NULL; ++ ++static GHashTable * ++disabled_repos_new (GError **error) ++{ ++ GHashTable *table; ++ GFile *file; ++ ++ GFileInputStream *is; ++ GDataInputStream *input; ++ ++ GError *e = NULL; ++ ++ g_debug ("reading disabled repos from %s", PK_BACKEND_REPO_FILE); ++ file = g_file_new_for_path (PK_BACKEND_REPO_FILE); ++ is = g_file_read (file, NULL, &e); ++ ++ if (is == NULL) { ++ g_object_unref (file); ++ g_propagate_error (error, e); ++ return NULL; ++ } ++ ++ table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); ++ input = g_data_input_stream_new (G_INPUT_STREAM (is)); ++ ++ /* read disabled repos line by line, ignoring comments */ ++ while (TRUE) { ++ gchar *line; ++ ++ line = g_data_input_stream_read_line (input, NULL, NULL, &e); ++ ++ if (line != NULL) { ++ g_strstrip (line); ++ } else { ++ break; ++ } ++ ++ if (*line == '\0' || *line == '#') { ++ g_free (line); ++ continue; ++ } ++ ++ g_hash_table_insert (table, line, GINT_TO_POINTER (1)); ++ } ++ ++ g_object_unref (input); ++ g_object_unref (is); ++ g_object_unref (file); ++ ++ if (e != NULL) { ++ g_hash_table_unref (table); ++ g_propagate_error (error, e); ++ return NULL; ++ } else { ++ return table; ++ } ++} ++ ++static void ++disabled_repos_free (GHashTable *table) ++{ ++ GHashTableIter iter; ++ GFile *file; ++ ++ GFileOutputStream *os; ++ GDataOutputStream *output; ++ ++ const gchar *line; ++ ++ g_return_if_fail (table != NULL); ++ ++ g_debug ("storing disabled repos in %s", PK_BACKEND_REPO_FILE); ++ file = g_file_new_for_path (PK_BACKEND_REPO_FILE); ++ os = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL); ++ ++ if (os == NULL) { ++ g_object_unref (file); ++ g_hash_table_unref (table); ++ return; ++ } ++ ++ g_hash_table_iter_init (&iter, table); ++ output = g_data_output_stream_new (G_OUTPUT_STREAM (os)); ++ ++ /* write all disabled repos line by line */ ++ while (g_hash_table_iter_next (&iter, (gpointer *) &line, NULL) && ++ g_data_output_stream_put_string (output, line, NULL, NULL) && ++ g_data_output_stream_put_byte (output, '\n', NULL, NULL)); ++ ++ g_object_unref (output); ++ g_object_unref (os); ++ g_object_unref (file); ++ ++ g_hash_table_unref (table); ++} ++ ++static gboolean ++disabled_repos_configure (GHashTable *table, GError **error) ++{ ++ const alpm_list_t *i; ++ ++ g_debug ("reading config from %s", PK_BACKEND_CONFIG_FILE); ++ ++ /* read configuration from pacman.conf file */ ++ if (!pk_backend_configure (PK_BACKEND_CONFIG_FILE, error)) { ++ return FALSE; ++ } ++ ++ /* disable disabled repos */ ++ for (i = alpm_option_get_syncdbs (); i != NULL;) { ++ pmdb_t *db = (pmdb_t *) i->data; ++ const gchar *repo = alpm_db_get_name (db); ++ ++ if (g_hash_table_lookup (table, repo) == NULL) { ++ /* repo is not disabled */ ++ i = i->next; ++ continue; ++ } ++ ++ if (alpm_db_unregister (db) < 0) { ++ g_set_error (error, ALPM_ERROR, pm_errno, "[%s]: %s", ++ repo, alpm_strerrorlast ()); ++ return FALSE; ++ } ++ ++ /* start again because the list gets invalidated */ ++ i = alpm_option_get_syncdbs (); ++ } ++ ++ return TRUE; ++} ++ ++gboolean ++pk_backend_initialize_databases (PkBackend *self, GError **error) ++{ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ disabled = disabled_repos_new (error); ++ if (disabled == NULL) { ++ return FALSE; ++ } ++ ++ if (!disabled_repos_configure (disabled, error)) { ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++void ++pk_backend_destroy_databases (PkBackend *self) ++{ ++ g_return_if_fail (self != NULL); ++ ++ if (disabled != NULL) { ++ disabled_repos_free (disabled); ++ } ++} ++ ++static gboolean ++pk_backend_repo_info (PkBackend *self, const gchar *repo, gboolean enabled) ++{ ++ gchar *description; ++ gboolean result; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (repo != NULL, FALSE); ++ ++ description = g_strdup_printf ("[%s]", repo); ++ result = pk_backend_repo_detail (self, repo, description, enabled); ++ g_free (description); ++ ++ return result; ++} ++ ++static gboolean ++pk_backend_get_repo_list_thread (PkBackend *self) ++{ ++ const alpm_list_t *i; ++ GHashTableIter iter; ++ gpointer key, value; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (disabled != NULL, FALSE); ++ ++ /* emit enabled repos */ ++ for (i = alpm_option_get_syncdbs (); i != NULL; i = i->next) { ++ pmdb_t *db = (pmdb_t *) i->data; ++ const gchar *repo = alpm_db_get_name (db); ++ ++ if (pk_backend_cancelled (self)) { ++ goto out; ++ } else { ++ pk_backend_repo_info (self, repo, TRUE); ++ } ++ } ++ ++ /* emit disabled repos */ ++ g_hash_table_iter_init (&iter, disabled); ++ while (g_hash_table_iter_next (&iter, &key, &value)) { ++ const gchar *repo = (const gchar *) key; ++ ++ if (pk_backend_cancelled (self)) { ++ goto out; ++ } else { ++ pk_backend_repo_info (self, repo, FALSE); ++ } ++ } ++ ++out: ++ return pk_backend_finish (self, NULL); ++} ++ ++void ++pk_backend_get_repo_list (PkBackend *self, PkBitfield filters) ++{ ++ g_return_if_fail (self != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, ++ pk_backend_get_repo_list_thread); ++} ++ ++static gboolean ++pk_backend_repo_enable_thread (PkBackend *self) ++{ ++ const gchar *repo; ++ ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (disabled != NULL, FALSE); ++ ++ repo = pk_backend_get_string (self, "repo_id"); ++ ++ g_return_val_if_fail (repo != NULL, FALSE); ++ ++ if (g_hash_table_remove (disabled, repo)) { ++ /* reload configuration to preserve ordering */ ++ if (disabled_repos_configure (disabled, &error)) { ++ pk_backend_repo_list_changed (self); ++ } ++ } else { ++ int code = PM_ERR_DB_NOT_NULL; ++ g_set_error (&error, ALPM_ERROR, code, "[%s]: %s", ++ repo, alpm_strerror (code)); ++ } ++ ++ if (error != NULL) { ++ pk_backend_error (self, error); ++ g_error_free (error); ++ } ++ ++ pk_backend_thread_finished (self); ++ return (error == NULL); ++} ++ ++static gboolean ++pk_backend_repo_disable_thread (PkBackend *self) ++{ ++ const alpm_list_t *i; ++ const gchar *repo; ++ ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (disabled != NULL, FALSE); ++ ++ repo = pk_backend_get_string (self, "repo_id"); ++ ++ g_return_val_if_fail (repo != NULL, FALSE); ++ ++ for (i = alpm_option_get_syncdbs (); i != NULL; i = i->next) { ++ pmdb_t *db = (pmdb_t *) i->data; ++ const gchar *name = alpm_db_get_name (db); ++ ++ if (g_strcmp0 (repo, name) == 0) { ++ if (alpm_db_unregister (db) < 0) { ++ g_set_error (&error, ALPM_ERROR, pm_errno, ++ "[%s]: %s", repo, ++ alpm_strerrorlast ()); ++ } else { ++ g_hash_table_insert (disabled, g_strdup (repo), ++ GINT_TO_POINTER (1)); ++ } ++ break; ++ } ++ } ++ ++ if (i == NULL) { ++ int code = PM_ERR_DB_NULL; ++ g_set_error (&error, ALPM_ERROR, code, "[%s]: %s", repo, ++ alpm_strerror (code)); ++ } ++ ++ if (error != NULL) { ++ pk_backend_error (self, error); ++ g_error_free (error); ++ } ++ ++ pk_backend_thread_finished (self); ++ return (error == NULL); ++} ++ ++void ++pk_backend_repo_enable (PkBackend *self, const gchar *repo_id, gboolean enabled) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (repo_id != NULL); ++ ++ pk_backend_set_status (self, PK_STATUS_ENUM_QUERY); ++ ++ if (enabled) { ++ pk_backend_thread_create (self, pk_backend_repo_enable_thread); ++ } else { ++ pk_backend_thread_create (self, pk_backend_repo_disable_thread); ++ } ++} +diff --git a/backends/alpm/pk-backend-databases.h b/backends/alpm/pk-backend-databases.h +new file mode 100644 +index 0000000..f9eb2f9 +--- /dev/null ++++ b/backends/alpm/pk-backend-databases.h +@@ -0,0 +1,30 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++ ++gboolean pk_backend_initialize_databases (PkBackend *self, ++ GError **error); ++ ++void pk_backend_destroy_databases (PkBackend *self); +diff --git a/backends/alpm/pk-backend-depends.c b/backends/alpm/pk-backend-depends.c +new file mode 100644 +index 0000000..8bb8567 +--- /dev/null ++++ b/backends/alpm/pk-backend-depends.c +@@ -0,0 +1,269 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++ ++#include "pk-backend-alpm.h" ++#include "pk-backend-depends.h" ++#include "pk-backend-error.h" ++#include "pk-backend-packages.h" ++ ++static pmpkg_t * ++alpm_list_find_pkg (const alpm_list_t *pkgs, const gchar *name) ++{ ++ g_return_val_if_fail (name != NULL, NULL); ++ ++ for (; pkgs != NULL; pkgs = pkgs->next) { ++ if (g_strcmp0 (name, alpm_pkg_get_name (pkgs->data)) == 0) { ++ return pkgs->data; ++ } ++ } ++ ++ return NULL; ++} ++ ++static alpm_list_t * ++pk_backend_find_provider (PkBackend *self, alpm_list_t *pkgs, ++ const gchar *depend, GError **error) ++{ ++ PkBitfield filters; ++ gboolean recursive, skip_local, skip_remote; ++ ++ pmpkg_t *provider; ++ alpm_list_t *pkgcache, *syncdbs; ++ ++ g_return_val_if_fail (self != NULL, pkgs); ++ g_return_val_if_fail (depend != NULL, pkgs); ++ g_return_val_if_fail (localdb != NULL, pkgs); ++ ++ recursive = pk_backend_get_bool (self, "recursive"); ++ filters = pk_backend_get_uint (self, "filters"); ++ skip_local = pk_bitfield_contain (filters, ++ PK_FILTER_ENUM_NOT_INSTALLED); ++ skip_remote = pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED); ++ ++ if (alpm_find_satisfier (pkgs, depend) != NULL) { ++ return pkgs; ++ } ++ ++ /* look for local dependencies */ ++ pkgcache = alpm_db_get_pkgcache (localdb); ++ provider = alpm_find_satisfier (pkgcache, depend); ++ ++ if (provider != NULL) { ++ if (!skip_local) { ++ pk_backend_pkg (self, provider, PK_INFO_ENUM_INSTALLED); ++ /* assume later dependencies will also be local */ ++ if (recursive) { ++ pkgs = alpm_list_add (pkgs, provider); ++ } ++ } ++ ++ return pkgs; ++ } ++ ++ /* look for remote dependencies */ ++ syncdbs = alpm_option_get_syncdbs (); ++ provider = alpm_find_dbs_satisfier (syncdbs, depend); ++ ++ if (provider != NULL) { ++ if (!skip_remote) { ++ pk_backend_pkg (self, provider, PK_INFO_ENUM_AVAILABLE); ++ } ++ /* keep looking for local dependencies */ ++ if (recursive) { ++ pkgs = alpm_list_add (pkgs, provider); ++ } ++ } else { ++ int code = PM_ERR_UNSATISFIED_DEPS; ++ g_set_error (error, ALPM_ERROR, code, "%s: %s", depend, ++ alpm_strerror (code)); ++ } ++ ++ return pkgs; ++} ++ ++static alpm_list_t * ++pk_backend_find_requirer (PkBackend *self, alpm_list_t *pkgs, const gchar *name, ++ GError **error) ++{ ++ pmpkg_t *requirer; ++ ++ g_return_val_if_fail (self != NULL, pkgs); ++ g_return_val_if_fail (name != NULL, pkgs); ++ g_return_val_if_fail (localdb != NULL, pkgs); ++ ++ if (alpm_list_find_pkg (pkgs, name) != NULL) { ++ return pkgs; ++ } ++ ++ /* look for local requirers */ ++ requirer = alpm_db_get_pkg (localdb, name); ++ ++ if (requirer != NULL) { ++ pk_backend_pkg (self, requirer, PK_INFO_ENUM_INSTALLED); ++ if (pk_backend_get_bool (self, "recursive")) { ++ pkgs = alpm_list_add (pkgs, requirer); ++ } ++ } else { ++ int code = PM_ERR_PKG_NOT_FOUND; ++ g_set_error (error, ALPM_ERROR, code, "%s: %s", name, ++ alpm_strerror (code)); ++ } ++ ++ return pkgs; ++} ++ ++static gboolean ++pk_backend_get_depends_thread (PkBackend *self) ++{ ++ gchar **packages; ++ alpm_list_t *i, *pkgs = NULL; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ packages = pk_backend_get_strv (self, "package_ids"); ++ ++ g_return_val_if_fail (packages != NULL, FALSE); ++ ++ /* construct an initial package list */ ++ for (; *packages != NULL; ++packages) { ++ pmpkg_t *pkg; ++ ++ if (pk_backend_cancelled (self)) { ++ break; ++ } ++ ++ pkg = pk_backend_find_pkg (self, *packages, &error); ++ if (pkg == NULL) { ++ break; ++ } ++ ++ pkgs = alpm_list_add (pkgs, pkg); ++ } ++ ++ /* package list might be modified along the way but that is ok */ ++ for (i = pkgs; i != NULL; i = i->next) { ++ const alpm_list_t *depends; ++ ++ if (pk_backend_cancelled (self) || error != NULL) { ++ break; ++ } ++ ++ depends = alpm_pkg_get_depends (i->data); ++ for (; depends != NULL; depends = depends->next) { ++ gchar *depend; ++ ++ if (pk_backend_cancelled (self) || error != NULL) { ++ break; ++ } ++ ++ depend = alpm_dep_compute_string (depends->data); ++ pkgs = pk_backend_find_provider (self, pkgs, depend, ++ &error); ++ g_free (depend); ++ } ++ } ++ ++ alpm_list_free (pkgs); ++ return pk_backend_finish (self, NULL); ++} ++ ++static gboolean ++pk_backend_get_requires_thread (PkBackend *self) ++{ ++ gchar **packages; ++ alpm_list_t *i, *pkgs = NULL; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ packages = pk_backend_get_strv (self, "package_ids"); ++ ++ g_return_val_if_fail (packages != NULL, FALSE); ++ ++ /* construct an initial package list */ ++ for (; *packages != NULL; ++packages) { ++ pmpkg_t *pkg; ++ ++ if (pk_backend_cancelled (self)) { ++ break; ++ } ++ ++ pkg = pk_backend_find_pkg (self, *packages, &error); ++ if (pkg == NULL) { ++ break; ++ } ++ ++ pkgs = alpm_list_add (pkgs, pkg); ++ } ++ ++ /* package list might be modified along the way but that is ok */ ++ for (i = pkgs; i != NULL; i = i->next) { ++ alpm_list_t *requiredby; ++ ++ if (pk_backend_cancelled (self) || error != NULL) { ++ break; ++ } ++ ++ requiredby = alpm_pkg_compute_requiredby (i->data); ++ for (; requiredby != NULL; requiredby = requiredby->next) { ++ if (pk_backend_cancelled (self) || error != NULL) { ++ break; ++ } ++ ++ pkgs = pk_backend_find_requirer (self, pkgs, ++ requiredby->data, ++ &error); ++ } ++ ++ FREELIST (requiredby); ++ } ++ ++ alpm_list_free (pkgs); ++ return pk_backend_finish (self, error); ++} ++ ++void ++pk_backend_get_depends (PkBackend *self, PkBitfield filters, ++ gchar **package_ids, gboolean recursive) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, ++ pk_backend_get_depends_thread); ++} ++ ++void ++pk_backend_get_requires (PkBackend *self, PkBitfield filters, ++ gchar **package_ids, gboolean recursive) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, ++ pk_backend_get_requires_thread); ++} +diff --git a/backends/alpm/pk-backend-depends.h b/backends/alpm/pk-backend-depends.h +new file mode 100644 +index 0000000..368965a +--- /dev/null ++++ b/backends/alpm/pk-backend-depends.h +@@ -0,0 +1,22 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ +diff --git a/backends/alpm/pk-backend-error.c b/backends/alpm/pk-backend-error.c +new file mode 100644 +index 0000000..6383175 +--- /dev/null ++++ b/backends/alpm/pk-backend-error.c +@@ -0,0 +1,203 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++ ++#include "pk-backend-error.h" ++ ++static void ++pk_backend_output_locked (PkBackend *self) ++{ ++ gchar *output; ++ ++ g_return_if_fail (self != NULL); ++ ++ output = g_strdup_printf ("If you are certain no other package manager " ++ "is running, you can remove %s\n", ++ alpm_option_get_lockfile ()); ++ pk_backend_output (self, output); ++ g_free (output); ++} ++ ++void ++pk_backend_error (PkBackend *self, GError *error) ++{ ++ PkErrorEnum code = PK_ERROR_ENUM_UNKNOWN; ++ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (error != NULL); ++ ++ if (error->domain == ALPM_ERROR) { ++ switch (error->code) { ++ case PM_ERR_MEMORY: ++ case PM_ERR_SYSTEM: ++ code = PK_ERROR_ENUM_OOM; ++ break; ++ ++ case PM_ERR_BADPERMS: ++ code = PK_ERROR_ENUM_NOT_AUTHORIZED; ++ break; ++ ++ case PM_ERR_NOT_A_FILE: ++ case PM_ERR_NOT_A_DIR: ++ code = PK_ERROR_ENUM_FILE_NOT_FOUND; ++ break; ++ ++ case PM_ERR_WRONG_ARGS: ++ case PM_ERR_HANDLE_NULL: ++ case PM_ERR_DB_NULL: ++ case PM_ERR_TRANS_NULL: ++ case PM_ERR_TRANS_NOT_INITIALIZED: ++ case PM_ERR_TRANS_NOT_PREPARED: ++ case PM_ERR_TRANS_NOT_LOCKED: ++ case PM_ERR_INVALID_REGEX: ++ code = PK_ERROR_ENUM_INTERNAL_ERROR; ++ break; ++ ++ case PM_ERR_DISK_SPACE: ++ code = PK_ERROR_ENUM_NO_SPACE_ON_DEVICE; ++ break; ++ ++ case PM_ERR_HANDLE_NOT_NULL: ++ case PM_ERR_DB_NOT_NULL: ++ case PM_ERR_TRANS_NOT_NULL: ++ code = PK_ERROR_ENUM_FAILED_INITIALIZATION; ++ break; ++ ++ case PM_ERR_HANDLE_LOCK: ++ code = PK_ERROR_ENUM_CANNOT_GET_LOCK; ++ pk_backend_output_locked (self); ++ break; ++ ++ case PM_ERR_DB_OPEN: ++ case PM_ERR_DB_NOT_FOUND: ++ case PM_ERR_PKG_REPO_NOT_FOUND: ++ code = PK_ERROR_ENUM_REPO_NOT_FOUND; ++ break; ++ ++ case PM_ERR_DB_CREATE: ++ code = PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG; ++ break; ++ ++ case PM_ERR_DB_VERSION: ++ case PM_ERR_DB_REMOVE: ++ code = PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR; ++ break; ++ ++ case PM_ERR_DB_WRITE: ++ code = PK_ERROR_ENUM_REPO_NOT_AVAILABLE; ++ break; ++ ++ case PM_ERR_SERVER_BAD_URL: ++ code = PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR; ++ break; ++ ++ case PM_ERR_SERVER_NONE: ++ code = PK_ERROR_ENUM_NO_MORE_MIRRORS_TO_TRY; ++ break; ++ ++ case PM_ERR_TRANS_DUP_TARGET: ++ case PM_ERR_TRANS_ABORT: ++ code = PK_ERROR_ENUM_TRANSACTION_ERROR; ++ break; ++ ++ case PM_ERR_TRANS_TYPE: ++ code = PK_ERROR_ENUM_CANNOT_CANCEL; ++ break; ++ ++ case PM_ERR_PKG_NOT_FOUND: ++ code = PK_ERROR_ENUM_PACKAGE_NOT_FOUND; ++ break; ++ ++ case PM_ERR_PKG_IGNORED: ++ code = PK_ERROR_ENUM_PACKAGE_INSTALL_BLOCKED; ++ break; ++ ++ case PM_ERR_PKG_INVALID: ++ case PM_ERR_PKG_OPEN: ++ case PM_ERR_PKG_INVALID_NAME: ++ case PM_ERR_DLT_INVALID: ++ code = PK_ERROR_ENUM_INVALID_PACKAGE_FILE; ++ break; ++ ++ case PM_ERR_PKG_CANT_REMOVE: ++ code = PK_ERROR_ENUM_PACKAGE_FAILED_TO_REMOVE; ++ break; ++ ++ case PM_ERR_PKG_INVALID_ARCH: ++ code = PK_ERROR_ENUM_INCOMPATIBLE_ARCHITECTURE; ++ break; ++ ++ case PM_ERR_DLT_PATCHFAILED: ++ code = PK_ERROR_ENUM_PACKAGE_FAILED_TO_BUILD; ++ break; ++ ++ case PM_ERR_UNSATISFIED_DEPS: ++ code = PK_ERROR_ENUM_DEP_RESOLUTION_FAILED; ++ break; ++ ++ case PM_ERR_CONFLICTING_DEPS: ++ code = PK_ERROR_ENUM_PACKAGE_CONFLICTS; ++ break; ++ ++ case PM_ERR_FILE_CONFLICTS: ++ code = PK_ERROR_ENUM_FILE_CONFLICTS; ++ break; ++ ++ case PM_ERR_RETRIEVE: ++ case PM_ERR_LIBFETCH: ++ case PM_ERR_EXTERNAL_DOWNLOAD: ++ code = PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED; ++ break; ++ ++ case PM_ERR_LIBARCHIVE: ++ code = PK_ERROR_ENUM_LOCAL_INSTALL_FAILED; ++ break; ++ ++ case PM_ERR_CONFIG_INVALID: ++ code = PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE; ++ break; ++ ++ case PM_ERR_PKG_HELD: ++ code = PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE; ++ break; ++ } ++ } ++ ++ pk_backend_error_code (self, code, "%s", error->message); ++} ++ ++void ++pk_backend_output (PkBackend *self, const gchar *output) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (output != NULL); ++ ++ pk_backend_message (self, PK_MESSAGE_ENUM_UNKNOWN, "%s", output); ++} ++ ++GQuark ++alpm_error_quark (void) ++{ ++ return g_quark_from_static_string ("alpm-error-quark"); ++} +diff --git a/backends/alpm/pk-backend-error.h b/backends/alpm/pk-backend-error.h +new file mode 100644 +index 0000000..b01b06d +--- /dev/null ++++ b/backends/alpm/pk-backend-error.h +@@ -0,0 +1,37 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++ ++#define ALPM_ERROR (alpm_error_quark ()) ++ ++enum { ++ PM_ERR_CONFIG_INVALID = 0x10000, ++ PM_ERR_PKG_HELD ++}; ++ ++void pk_backend_error (PkBackend *self, GError *error); ++ ++void pk_backend_output (PkBackend *self, const gchar *output); ++ ++GQuark alpm_error_quark (void); +diff --git a/backends/alpm/pk-backend-groups.c b/backends/alpm/pk-backend-groups.c +new file mode 100644 +index 0000000..59e304d +--- /dev/null ++++ b/backends/alpm/pk-backend-groups.c +@@ -0,0 +1,153 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++ ++#include "pk-backend-groups.h" ++ ++static GHashTable *grps = NULL; ++static PkBitfield groups = 0; ++ ++static GHashTable * ++group_map_new (GError **error) ++{ ++ GHashTable *map; ++ GFile *file; ++ ++ GFileInputStream *is; ++ GDataInputStream *input; ++ ++ GError *e = NULL; ++ ++ g_debug ("reading group map from %s", PK_BACKEND_GROUP_FILE); ++ file = g_file_new_for_path (PK_BACKEND_GROUP_FILE); ++ is = g_file_read (file, NULL, &e); ++ ++ if (is == NULL) { ++ g_object_unref (file); ++ g_propagate_error (error, e); ++ return NULL; ++ } ++ ++ map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); ++ input = g_data_input_stream_new (G_INPUT_STREAM (is)); ++ ++ /* read groups line by line, ignoring comments */ ++ while (TRUE) { ++ PkGroupEnum group; ++ gchar *key, *value; ++ ++ value = g_data_input_stream_read_line (input, NULL, NULL, &e); ++ ++ if (value != NULL) { ++ g_strstrip (value); ++ } else { ++ break; ++ } ++ ++ if (*value == '\0' || *value == '#') { ++ g_free (value); ++ continue; ++ } ++ ++ /* line format: grp (space|tab)+ group */ ++ key = strsep (&value, " "); ++ g_strchomp (key); ++ ++ if (value == NULL) { ++ /* safe to cast as it is never freed or modified */ ++ value = (gchar *) "other"; ++ group = PK_GROUP_ENUM_OTHER; ++ } else { ++ g_strchug (value); ++ group = pk_group_enum_from_string (value); ++ } ++ ++ if (group != PK_GROUP_ENUM_UNKNOWN) { ++ /* key and value are allocated together */ ++ g_hash_table_replace (map, key, value); ++ pk_bitfield_add (groups, group); ++ } ++ } ++ ++ g_object_unref (input); ++ g_object_unref (is); ++ g_object_unref (file); ++ ++ if (e != NULL) { ++ g_hash_table_unref (map); ++ g_propagate_error (error, e); ++ return NULL; ++ } else { ++ return map; ++ } ++} ++ ++gboolean ++pk_backend_initialize_groups (PkBackend *self, GError **error) ++{ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ grps = group_map_new (error); ++ ++ return (grps != NULL); ++} ++ ++void ++pk_backend_destroy_groups (PkBackend *self) ++{ ++ g_return_if_fail (self != NULL); ++ ++ if (grps != NULL) { ++ g_hash_table_unref (grps); ++ } ++} ++ ++const gchar * ++alpm_pkg_get_group (pmpkg_t *pkg) ++{ ++ const alpm_list_t *i; ++ ++ g_return_val_if_fail (pkg != NULL, NULL); ++ g_return_val_if_fail (grps != NULL, NULL); ++ ++ /* use the first group that we recognise */ ++ for (i = alpm_pkg_get_groups (pkg); i != NULL; i = i->next) { ++ gpointer value = g_hash_table_lookup (grps, i->data); ++ ++ if (value != NULL) { ++ return (const gchar *) value; ++ } ++ } ++ ++ return "other"; ++} ++ ++PkBitfield ++pk_backend_get_groups (PkBackend *self) ++{ ++ g_return_val_if_fail (self != NULL, 0); ++ ++ return groups; ++} +diff --git a/backends/alpm/pk-backend-groups.h b/backends/alpm/pk-backend-groups.h +new file mode 100644 +index 0000000..28dcf65 +--- /dev/null ++++ b/backends/alpm/pk-backend-groups.h +@@ -0,0 +1,32 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++ ++gboolean pk_backend_initialize_groups (PkBackend *self, ++ GError **error); ++ ++void pk_backend_destroy_groups (PkBackend *self); ++ ++const gchar *alpm_pkg_get_group (pmpkg_t *pkg); +diff --git a/backends/alpm/pk-backend-install.c b/backends/alpm/pk-backend-install.c +new file mode 100644 +index 0000000..65a6c11 +--- /dev/null ++++ b/backends/alpm/pk-backend-install.c +@@ -0,0 +1,124 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++ ++#include "pk-backend-alpm.h" ++#include "pk-backend-error.h" ++#include "pk-backend-install.h" ++#include "pk-backend-transaction.h" ++ ++static gint ++alpm_add_file (const gchar *filename) ++{ ++ pmpkg_t *pkg; ++ ++ g_return_val_if_fail (filename != NULL, -1); ++ ++ if (alpm_pkg_load (filename, 1, &pkg) < 0) { ++ return -1; ++ } ++ ++ if (alpm_add_pkg (pkg) < 0) { ++ alpm_pkg_free (pkg); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static gboolean ++pk_backend_transaction_add_targets (PkBackend *self, GError **error) ++{ ++ gchar **paths; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ paths = pk_backend_get_strv (self, "full_paths"); ++ ++ g_return_val_if_fail (paths != NULL, FALSE); ++ ++ for (; *paths != NULL; ++paths) { ++ if (alpm_add_file (*paths) < 0) { ++ g_set_error (error, ALPM_ERROR, pm_errno, "%s: %s", ++ *paths, alpm_strerrorlast ()); ++ return FALSE; ++ } ++ } ++ ++ return TRUE; ++} ++ ++static gboolean ++pk_backend_simulate_install_files_thread (PkBackend *self) ++{ ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ if (pk_backend_transaction_initialize (self, 0, &error) && ++ pk_backend_transaction_add_targets (self, &error) && ++ pk_backend_transaction_simulate (self, &error)) { ++ pk_backend_transaction_packages (self); ++ } ++ ++ return pk_backend_transaction_finish (self, error); ++} ++ ++static gboolean ++pk_backend_install_files_thread (PkBackend *self) ++{ ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ if (pk_backend_transaction_initialize (self, 0, &error) && ++ pk_backend_transaction_add_targets (self, &error) && ++ pk_backend_transaction_simulate (self, &error)) { ++ pk_backend_transaction_commit (self, &error); ++ } ++ ++ return pk_backend_transaction_finish (self, error); ++} ++ ++void ++pk_backend_simulate_install_files (PkBackend *self, gchar **paths) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (paths != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_SETUP, ++ pk_backend_simulate_install_files_thread); ++} ++ ++void ++pk_backend_install_files (PkBackend *self, gboolean only_trusted, ++ gchar **full_paths) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (full_paths != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_SETUP, ++ pk_backend_install_files_thread); ++} +diff --git a/backends/alpm/pk-backend-install.h b/backends/alpm/pk-backend-install.h +new file mode 100644 +index 0000000..368965a +--- /dev/null ++++ b/backends/alpm/pk-backend-install.h +@@ -0,0 +1,22 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ +diff --git a/backends/alpm/pk-backend-packages.c b/backends/alpm/pk-backend-packages.c +new file mode 100644 +index 0000000..e9a7c94 +--- /dev/null ++++ b/backends/alpm/pk-backend-packages.c +@@ -0,0 +1,363 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "pk-backend-alpm.h" ++#include "pk-backend-error.h" ++#include "pk-backend-groups.h" ++#include "pk-backend-packages.h" ++ ++gchar * ++alpm_pkg_build_id (pmpkg_t *pkg) ++{ ++ const gchar *name, *version, *arch, *repo; ++ pmdb_t *db; ++ ++ g_return_val_if_fail (pkg != NULL, NULL); ++ g_return_val_if_fail (localdb != NULL, NULL); ++ ++ name = alpm_pkg_get_name (pkg); ++ version = alpm_pkg_get_version (pkg); ++ ++ arch = alpm_pkg_get_arch (pkg); ++ if (arch == NULL) { ++ arch = "any"; ++ } ++ ++ db = alpm_pkg_get_db (pkg); ++ /* TODO: check */ ++ if (db == NULL || db == localdb) { ++ repo = "installed"; ++ } else { ++ repo = alpm_db_get_name (db); ++ } ++ ++ return pk_package_id_build (name, version, arch, repo); ++} ++ ++void ++pk_backend_pkg (PkBackend *self, pmpkg_t *pkg, PkInfoEnum info) ++{ ++ gchar *package; ++ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (pkg != NULL); ++ ++ package = alpm_pkg_build_id (pkg); ++ pk_backend_package (self, info, package, alpm_pkg_get_desc (pkg)); ++ g_free (package); ++} ++ ++pmpkg_t * ++pk_backend_find_pkg (PkBackend *self, const gchar *package_id, GError **error) ++{ ++ gchar **package; ++ const gchar *repo_id; ++ pmdb_t *db = NULL; ++ pmpkg_t *pkg; ++ ++ g_return_val_if_fail (self != NULL, NULL); ++ g_return_val_if_fail (package_id != NULL, NULL); ++ g_return_val_if_fail (localdb != NULL, NULL); ++ ++ package = pk_package_id_split (package_id); ++ repo_id = package[PK_PACKAGE_ID_DATA]; ++ ++ /* find the database to search in */ ++ if (g_strcmp0 (repo_id, "installed") == 0) { ++ db = localdb; ++ } else { ++ const alpm_list_t *i; ++ for (i = alpm_option_get_syncdbs (); i != NULL; i = i->next) { ++ const gchar *repo = alpm_db_get_name (i->data); ++ ++ if (g_strcmp0 (repo, repo_id) == 0) { ++ db = i->data; ++ break; ++ } ++ } ++ } ++ ++ if (db != NULL) { ++ pkg = alpm_db_get_pkg (db, package[PK_PACKAGE_ID_NAME]); ++ } else { ++ pkg = NULL; ++ } ++ ++ if (pkg != NULL) { ++ const gchar *version = alpm_pkg_get_version (pkg); ++ if (g_strcmp0 (version, package[PK_PACKAGE_ID_VERSION]) != 0) { ++ pkg = NULL; ++ } ++ } ++ ++ if (pkg == NULL) { ++ int code = PM_ERR_PKG_NOT_FOUND; ++ g_set_error (error, ALPM_ERROR, code, "%s: %s", package_id, ++ alpm_strerror (code)); ++ } ++ g_strfreev (package); ++ return pkg; ++} ++ ++static gboolean ++pk_backend_resolve_package (PkBackend *self, const gchar *package, ++ GError **error) ++{ ++ pmpkg_t *pkg; ++ ++ PkBitfield filters; ++ gboolean skip_local, skip_remote; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (package != NULL, FALSE); ++ g_return_val_if_fail (localdb != NULL, FALSE); ++ ++ pkg = pk_backend_find_pkg (self, package, error); ++ if (pkg == NULL) { ++ return FALSE; ++ } ++ ++ filters = pk_backend_get_uint (self, "filters"); ++ skip_local = pk_bitfield_contain (filters, ++ PK_FILTER_ENUM_NOT_INSTALLED); ++ skip_remote = pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED); ++ ++ if (alpm_pkg_get_db (pkg) == localdb) { ++ if (!skip_local) { ++ pk_backend_pkg (self, pkg, PK_INFO_ENUM_INSTALLED); ++ } ++ } else { ++ if (!skip_remote) { ++ pk_backend_pkg (self, pkg, PK_INFO_ENUM_AVAILABLE); ++ } ++ } ++ ++ return TRUE; ++} ++ ++static gboolean ++pk_backend_resolve_name (PkBackend *self, const gchar *name, GError **error) ++{ ++ pmpkg_t *pkg; ++ int code; ++ ++ PkBitfield filters; ++ gboolean skip_local, skip_remote; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (name != NULL, FALSE); ++ g_return_val_if_fail (localdb != NULL, FALSE); ++ ++ filters = pk_backend_get_uint (self, "filters"); ++ skip_local = pk_bitfield_contain (filters, ++ PK_FILTER_ENUM_NOT_INSTALLED); ++ skip_remote = pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED); ++ ++ pkg = alpm_db_get_pkg (localdb, name); ++ if (pkg != NULL) { ++ if (!skip_local) { ++ pk_backend_pkg (self, pkg, PK_INFO_ENUM_INSTALLED); ++ return TRUE; ++ } ++ } else if (!skip_remote) { ++ const alpm_list_t *i; ++ for (i = alpm_option_get_syncdbs (); i != NULL; i = i->next) { ++ pkg = alpm_db_get_pkg (i->data, name); ++ if (pkg != NULL) { ++ pk_backend_pkg (self, pkg, ++ PK_INFO_ENUM_AVAILABLE); ++ return TRUE; ++ } ++ } ++ } ++ ++ code = PM_ERR_PKG_NOT_FOUND; ++ g_set_error (error, ALPM_ERROR, code, "%s: %s", name, ++ alpm_strerror (code)); ++ return FALSE; ++} ++ ++static gboolean ++pk_backend_resolve_thread (PkBackend *self) ++{ ++ gchar **packages; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ packages = pk_backend_get_strv (self, "package_ids"); ++ ++ g_return_val_if_fail (packages != NULL, FALSE); ++ ++ for (; *packages != NULL; ++packages) { ++ if (pk_backend_cancelled (self)) { ++ break; ++ } ++ ++ /* find a package with the given id or name */ ++ if (pk_package_id_check (*packages)) { ++ if (!pk_backend_resolve_package (self, *packages, ++ &error)) { ++ break; ++ } ++ } else { ++ if (!pk_backend_resolve_name (self, *packages, ++ &error)) { ++ break; ++ } ++ } ++ } ++ ++ return pk_backend_finish (self, error); ++} ++ ++void ++pk_backend_resolve (PkBackend *self, PkBitfield filters, gchar **package_ids) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, pk_backend_resolve_thread); ++} ++ ++static gboolean ++pk_backend_get_details_thread (PkBackend *self) ++{ ++ gchar **packages; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (localdb != NULL, FALSE); ++ ++ packages = pk_backend_get_strv (self, "package_ids"); ++ ++ g_return_val_if_fail (packages != NULL, FALSE); ++ ++ for (; *packages != NULL; ++packages) { ++ pmpkg_t *pkg; ++ const alpm_list_t *i; ++ ++ GString *licenses; ++ PkGroupEnum group; ++ const gchar *desc, *url; ++ gulong size; ++ ++ if (pk_backend_cancelled (self)) { ++ break; ++ } ++ ++ pkg = pk_backend_find_pkg (self, *packages, &error); ++ if (pkg == NULL) { ++ break; ++ } ++ ++ licenses = g_string_new (""); ++ i = alpm_pkg_get_licenses (pkg); ++ for (; i != NULL; i = i->next) { ++ /* assume OR although it may not be correct */ ++ g_string_append_printf (licenses, " or %s", ++ (const gchar *) i->data); ++ } ++ if (licenses->len == 0) { ++ g_string_append (licenses, " or Unknown"); ++ } ++ ++ group = pk_group_enum_from_string (alpm_pkg_get_group (pkg)); ++ desc = alpm_pkg_get_desc (pkg); ++ url = alpm_pkg_get_url (pkg); ++ ++ if (alpm_pkg_get_db (pkg) == localdb) { ++ size = alpm_pkg_get_isize (pkg); ++ } else { ++ size = alpm_pkg_download_size (pkg); ++ } ++ ++ pk_backend_details (self, *packages, licenses->str + 4, group, ++ desc, url, size); ++ g_string_free (licenses, TRUE); ++ } ++ ++ return pk_backend_finish (self, error); ++} ++ ++void ++pk_backend_get_details (PkBackend *self, gchar **package_ids) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, ++ pk_backend_get_details_thread); ++} ++ ++static gboolean ++pk_backend_get_files_thread (PkBackend *self) ++{ ++ gchar **packages; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ packages = pk_backend_get_strv (self, "package_ids"); ++ ++ g_return_val_if_fail (packages != NULL, FALSE); ++ ++ for (; *packages != NULL; ++packages) { ++ pmpkg_t *pkg; ++ const alpm_list_t *i; ++ ++ GString *files; ++ const gchar *root; ++ ++ if (pk_backend_cancelled (self)) { ++ break; ++ } ++ ++ pkg = pk_backend_find_pkg (self, *packages, &error); ++ if (pkg == NULL) { ++ break; ++ } ++ ++ files = g_string_new (""); ++ root = alpm_option_get_root (); ++ for (i = alpm_pkg_get_files (pkg); i != NULL; i = i->next) { ++ g_string_append_printf (files, ";%s%s", root, ++ (const gchar *) i->data); ++ } ++ ++ pk_backend_files (self, *packages, files->str + 1); ++ g_string_free (files, TRUE); ++ } ++ ++ return pk_backend_finish (self, error); ++} ++ ++void ++pk_backend_get_files (PkBackend *self, gchar **package_ids) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, ++ pk_backend_get_files_thread); ++} +diff --git a/backends/alpm/pk-backend-packages.h b/backends/alpm/pk-backend-packages.h +new file mode 100644 +index 0000000..4b2d7f8 +--- /dev/null ++++ b/backends/alpm/pk-backend-packages.h +@@ -0,0 +1,33 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++ ++gchar *alpm_pkg_build_id (pmpkg_t *pkg); ++ ++void pk_backend_pkg (PkBackend *self, pmpkg_t *pkg, ++ PkInfoEnum info); ++ ++pmpkg_t *pk_backend_find_pkg (PkBackend *self, const gchar *package_id, ++ GError **error); +diff --git a/backends/alpm/pk-backend-remove.c b/backends/alpm/pk-backend-remove.c +new file mode 100644 +index 0000000..03329b1 +--- /dev/null ++++ b/backends/alpm/pk-backend-remove.c +@@ -0,0 +1,167 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++ ++#include "pk-backend-alpm.h" ++#include "pk-backend-error.h" ++#include "pk-backend-remove.h" ++#include "pk-backend-transaction.h" ++ ++static gint ++alpm_remove_local (const gchar *name) ++{ ++ pmpkg_t *pkg; ++ ++ g_return_val_if_fail (name != NULL, -1); ++ g_return_val_if_fail (localdb != NULL, -1); ++ ++ pkg = alpm_db_get_pkg (localdb, name); ++ if (pkg == NULL) { ++ pm_errno = PM_ERR_PKG_NOT_FOUND; ++ return -1; ++ } ++ ++ return alpm_remove_pkg (pkg); ++} ++ ++static gboolean ++pk_backend_transaction_remove_targets (PkBackend *self, GError **error) ++{ ++ gchar **packages; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ packages = pk_backend_get_strv (self, "package_ids"); ++ ++ g_return_val_if_fail (packages != NULL, FALSE); ++ ++ for (; *packages != NULL; ++packages) { ++ gchar **package = pk_package_id_split (*packages); ++ gchar *name = package[PK_PACKAGE_ID_NAME]; ++ ++ if (alpm_remove_local (name) < 0) { ++ g_set_error (error, ALPM_ERROR, pm_errno, "%s: %s", ++ name, alpm_strerrorlast ()); ++ g_strfreev (package); ++ return FALSE; ++ } ++ ++ g_strfreev (package); ++ } ++ ++ return TRUE; ++} ++ ++static gboolean ++pk_backend_transaction_remove_simulate (PkBackend *self, GError **error) ++{ ++ const alpm_list_t *i; ++ ++ if (!pk_backend_transaction_simulate (self, error)) { ++ return FALSE; ++ } ++ ++ for (i = alpm_trans_get_remove (); i != NULL; i = i->next) { ++ const gchar *name = alpm_pkg_get_name (i->data); ++ if (alpm_list_find_str (holdpkgs, name)) { ++ g_set_error (error, ALPM_ERROR, PM_ERR_PKG_HELD, ++ "%s: %s", name, ++ "could not remove HoldPkg"); ++ return FALSE; ++ } ++ } ++ ++ return TRUE; ++} ++ ++static gboolean ++pk_backend_simulate_remove_packages_thread (PkBackend *self) ++{ ++ pmtransflag_t flags = PM_TRANS_FLAG_CASCADE; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ /* remove unneeded packages that were required by those to be removed */ ++ if (pk_backend_get_bool (self, "autoremove")) { ++ flags |= PM_TRANS_FLAG_RECURSE; ++ } ++ ++ if (pk_backend_transaction_initialize (self, flags, &error) && ++ pk_backend_transaction_remove_targets (self, &error) && ++ pk_backend_transaction_remove_simulate (self, &error)) { ++ pk_backend_transaction_packages (self); ++ } ++ ++ return pk_backend_transaction_finish (self, error); ++} ++ ++static gboolean ++pk_backend_remove_packages_thread (PkBackend *self) ++{ ++ pmtransflag_t flags = 0; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ /* remove packages that depend on those to be removed */ ++ if (pk_backend_get_bool (self, "allow_deps")) { ++ flags |= PM_TRANS_FLAG_CASCADE; ++ } ++ /* remove unneeded packages that were required by those to be removed */ ++ if (pk_backend_get_bool (self, "autoremove")) { ++ flags |= PM_TRANS_FLAG_RECURSE; ++ } ++ ++ if (pk_backend_transaction_initialize (self, flags, &error) && ++ pk_backend_transaction_remove_targets (self, &error) && ++ pk_backend_transaction_remove_simulate (self, &error)) { ++ pk_backend_transaction_commit (self, &error); ++ } ++ ++ return pk_backend_transaction_finish (self, error); ++} ++ ++void ++pk_backend_simulate_remove_packages (PkBackend *self, gchar **package_ids, ++ gboolean autoremove) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_SETUP, ++ pk_backend_simulate_remove_packages_thread); ++} ++ ++void ++pk_backend_remove_packages (PkBackend *self, gchar **package_ids, ++ gboolean allow_deps, gboolean autoremove) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_SETUP, ++ pk_backend_remove_packages_thread); ++} +diff --git a/backends/alpm/pk-backend-remove.h b/backends/alpm/pk-backend-remove.h +new file mode 100644 +index 0000000..368965a +--- /dev/null ++++ b/backends/alpm/pk-backend-remove.h +@@ -0,0 +1,22 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ +diff --git a/backends/alpm/pk-backend-search.c b/backends/alpm/pk-backend-search.c +new file mode 100644 +index 0000000..592472d +--- /dev/null ++++ b/backends/alpm/pk-backend-search.c +@@ -0,0 +1,450 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++#include ++ ++#include "pk-backend-alpm.h" ++#include "pk-backend-groups.h" ++#include "pk-backend-packages.h" ++#include "pk-backend-search.h" ++ ++static gpointer ++pk_backend_pattern_needle (const gchar *needle, GError **error) ++{ ++ return (gpointer) needle; ++} ++ ++static gpointer ++pk_backend_pattern_regex (const gchar *needle, GError **error) ++{ ++ gchar *pattern; ++ GRegex *regex; ++ ++ g_return_val_if_fail (needle != NULL, NULL); ++ ++ pattern = g_regex_escape_string (needle, -1); ++ regex = g_regex_new (pattern, G_REGEX_CASELESS, 0, error); ++ g_free (pattern); ++ ++ return regex; ++} ++ ++static gpointer ++pk_backend_pattern_chroot (const gchar *needle, GError **error) ++{ ++ g_return_val_if_fail (needle != NULL, NULL); ++ ++ if (G_IS_DIR_SEPARATOR (*needle)) { ++ const gchar *file = needle, *root = alpm_option_get_root (); ++ ++ /* adjust needle to the correct prefix */ ++ for (; *file == *root; ++file, ++root) { ++ if (*root == '\0') { ++ needle = file - 1; ++ break; ++ } else if (*file == '\0') { ++ break; ++ } ++ } ++ } ++ ++ return (gpointer) needle; ++} ++ ++static gboolean ++pk_backend_match_all (pmpkg_t *pkg, gpointer pattern) ++{ ++ g_return_val_if_fail (pkg != NULL, FALSE); ++ g_return_val_if_fail (pattern != NULL, FALSE); ++ ++ /* match all packages */ ++ return TRUE; ++} ++ ++static gboolean ++pk_backend_match_details (pmpkg_t *pkg, GRegex *regex) ++{ ++ const gchar *desc; ++ pmdb_t *db; ++ const alpm_list_t *i; ++ ++ g_return_val_if_fail (pkg != NULL, FALSE); ++ g_return_val_if_fail (regex != NULL, FALSE); ++ ++ /* match the name first... */ ++ if (g_regex_match (regex, alpm_pkg_get_name (pkg), 0, NULL)) { ++ return TRUE; ++ } ++ ++ /* ... then the description... */ ++ desc = alpm_pkg_get_desc (pkg); ++ if (desc != NULL && g_regex_match (regex, desc, 0, NULL)) { ++ return TRUE; ++ } ++ ++ /* ... then the database... */ ++ db = alpm_pkg_get_db (pkg); ++ if (db != NULL && g_regex_match (regex, alpm_db_get_name (db), ++ G_REGEX_MATCH_ANCHORED, NULL)) { ++ return TRUE; ++ } ++ ++ /* ... then the licenses */ ++ for (i = alpm_pkg_get_licenses (pkg); i != NULL; i = i->next) { ++ if (g_regex_match (regex, i->data, G_REGEX_MATCH_ANCHORED, ++ NULL)) { ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++} ++ ++static gboolean ++pk_backend_match_file (pmpkg_t *pkg, const gchar *needle) ++{ ++ const alpm_list_t *i; ++ ++ g_return_val_if_fail (pkg != NULL, FALSE); ++ g_return_val_if_fail (needle != NULL, FALSE); ++ ++ /* match any file the package contains */ ++ if (G_IS_DIR_SEPARATOR (*needle)) { ++ for (i = alpm_pkg_get_files (pkg); i != NULL; i = i->next) { ++ /* match the full path of file */ ++ if (g_strcmp0 (i->data, needle + 1) == 0) { ++ return TRUE; ++ } ++ } ++ } else { ++ for (i = alpm_pkg_get_files (pkg); i != NULL; i = i->next) { ++ const gchar *file = strrchr (i->data, G_DIR_SEPARATOR); ++ if (file == NULL) { ++ file = i->data; ++ } else { ++ ++file; ++ } ++ ++ /* match the basename of file */ ++ if (g_strcmp0 (file, needle) == 0) { ++ return TRUE; ++ } ++ } ++ } ++ ++ return FALSE; ++} ++ ++static gboolean ++pk_backend_match_group (pmpkg_t *pkg, const gchar *needle) ++{ ++ g_return_val_if_fail (pkg != NULL, FALSE); ++ g_return_val_if_fail (needle != NULL, FALSE); ++ ++ /* match the group the package is in */ ++ return g_strcmp0 (needle, alpm_pkg_get_group (pkg)) == 0; ++} ++ ++static gboolean ++pk_backend_match_name (pmpkg_t *pkg, GRegex *regex) ++{ ++ g_return_val_if_fail (pkg != NULL, FALSE); ++ g_return_val_if_fail (regex != NULL, FALSE); ++ ++ /* match the name of the package */ ++ return g_regex_match (regex, alpm_pkg_get_name (pkg), 0, NULL); ++} ++ ++static gboolean ++pk_backend_match_provides (pmpkg_t *pkg, gpointer pattern) ++{ ++ /* TODO: implement GStreamer codecs, Pango fonts, etc. */ ++ const alpm_list_t *i; ++ ++ g_return_val_if_fail (pkg != NULL, FALSE); ++ g_return_val_if_fail (pattern != NULL, FALSE); ++ ++ /* match features provided by package */ ++ for (i = alpm_pkg_get_provides (pkg); i != NULL; i = i->next) { ++ const gchar *needle = pattern, *name = i->data; ++ ++ for (; *needle == *name; ++needle, ++name) { ++ if (*needle == '\0') { ++ if (*name == '\0' || *name == '=') { ++ return TRUE; ++ } else { ++ break; ++ } ++ } ++ } ++ } ++ ++ return FALSE; ++} ++ ++typedef enum { ++ SEARCH_TYPE_ALL, ++ SEARCH_TYPE_DETAILS, ++ SEARCH_TYPE_FILES, ++ SEARCH_TYPE_GROUP, ++ SEARCH_TYPE_NAME, ++ SEARCH_TYPE_PROVIDES, ++ SEARCH_TYPE_LAST ++} SearchType; ++ ++typedef gpointer (*PatternFunc) (const gchar *needle, GError **error); ++typedef gboolean (*MatchFunc) (pmpkg_t *pkg, gpointer pattern); ++ ++static PatternFunc pattern_funcs[] = { ++ pk_backend_pattern_needle, ++ pk_backend_pattern_regex, ++ pk_backend_pattern_chroot, ++ pk_backend_pattern_needle, ++ pk_backend_pattern_regex, ++ pk_backend_pattern_needle ++}; ++ ++static GDestroyNotify pattern_frees[] = { ++ NULL, ++ (GDestroyNotify) g_regex_unref, ++ NULL, ++ NULL, ++ (GDestroyNotify) g_regex_unref, ++ NULL ++}; ++ ++static MatchFunc match_funcs[] = { ++ pk_backend_match_all, ++ (MatchFunc) pk_backend_match_details, ++ (MatchFunc) pk_backend_match_file, ++ (MatchFunc) pk_backend_match_group, ++ (MatchFunc) pk_backend_match_name, ++ pk_backend_match_provides ++}; ++ ++static gboolean ++alpm_pkg_is_local (pmpkg_t *pkg) ++{ ++ pmpkg_t *local; ++ ++ g_return_val_if_fail (pkg != NULL, FALSE); ++ g_return_val_if_fail (localdb != NULL, FALSE); ++ ++ /* find an installed package with the same name */ ++ local = alpm_db_get_pkg (localdb, alpm_pkg_get_name (pkg)); ++ if (local == NULL) { ++ return FALSE; ++ } ++ ++ /* make sure the installed version is the same */ ++ if (alpm_pkg_vercmp (alpm_pkg_get_version (local), ++ alpm_pkg_get_version (pkg)) != 0) { ++ return FALSE; ++ } ++ ++ /* make sure the installed arch is the same */ ++ if (g_strcmp0 (alpm_pkg_get_arch (local), ++ alpm_pkg_get_arch (pkg)) != 0) { ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++static void ++pk_backend_search_db (PkBackend *self, pmdb_t *db, MatchFunc match, ++ const alpm_list_t *patterns) ++{ ++ const alpm_list_t *i, *j; ++ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (db != NULL); ++ g_return_if_fail (match != NULL); ++ ++ /* emit packages that match all search terms */ ++ for (i = alpm_db_get_pkgcache (db); i != NULL; i = i->next) { ++ if (pk_backend_cancelled (self)) { ++ break; ++ } ++ ++ for (j = patterns; j != NULL; j = j->next) { ++ if (!match (i->data, j->data)) { ++ break; ++ } ++ } ++ ++ /* all search terms matched */ ++ if (j == NULL) { ++ if (db == localdb) { ++ pk_backend_pkg (self, i->data, ++ PK_INFO_ENUM_INSTALLED); ++ } else if (!alpm_pkg_is_local (i->data)) { ++ pk_backend_pkg (self, i->data, ++ PK_INFO_ENUM_AVAILABLE); ++ } ++ } ++ } ++} ++ ++static gboolean ++pk_backend_search_thread (PkBackend *self) ++{ ++ gchar **needles; ++ SearchType type; ++ ++ PatternFunc pattern_func; ++ GDestroyNotify pattern_free; ++ MatchFunc match_func; ++ ++ PkBitfield filters; ++ gboolean skip_local, skip_remote; ++ ++ const alpm_list_t *i; ++ alpm_list_t *patterns = NULL; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (localdb != NULL, FALSE); ++ ++ needles = pk_backend_get_strv (self, "search"); ++ type = pk_backend_get_uint (self, "search-type"); ++ ++ g_return_val_if_fail (needles != NULL, FALSE); ++ g_return_val_if_fail (type < SEARCH_TYPE_LAST, FALSE); ++ ++ pattern_func = pattern_funcs[type]; ++ pattern_free = pattern_frees[type]; ++ match_func = match_funcs[type]; ++ ++ g_return_val_if_fail (pattern_func != NULL, FALSE); ++ g_return_val_if_fail (match_func != NULL, FALSE); ++ ++ filters = pk_backend_get_uint (self, "filters"); ++ skip_local = pk_bitfield_contain (filters, ++ PK_FILTER_ENUM_NOT_INSTALLED); ++ skip_remote = pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED); ++ ++ /* convert search terms to the pattern requested */ ++ for (; *needles != NULL; ++needles) { ++ gpointer pattern = pattern_func (*needles, &error); ++ ++ if (pattern == NULL) { ++ goto out; ++ } ++ ++ patterns = alpm_list_add (patterns, pattern); ++ } ++ ++ /* find installed packages first */ ++ if (!skip_local) { ++ pk_backend_search_db (self, localdb, match_func, patterns); ++ } ++ ++ if (skip_remote) { ++ goto out; ++ } ++ ++ for (i = alpm_option_get_syncdbs (); i != NULL; i = i->next) { ++ if (pk_backend_cancelled (self)) { ++ break; ++ } ++ ++ pk_backend_search_db (self, i->data, match_func, patterns); ++ } ++ ++out: ++ if (pattern_free != NULL) { ++ alpm_list_free_inner (patterns, pattern_free); ++ } ++ alpm_list_free (patterns); ++ return pk_backend_finish (self, error); ++} ++ ++void ++pk_backend_get_packages (PkBackend *self, PkBitfield filters) ++{ ++ g_return_if_fail (self != NULL); ++ ++ /* provide a dummy needle */ ++ pk_backend_set_strv (self, "search", g_strsplit ("", ";", 0)); ++ ++ pk_backend_set_uint (self, "search-type", SEARCH_TYPE_ALL); ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, pk_backend_search_thread); ++} ++ ++void ++pk_backend_search_details (PkBackend *self, PkBitfield filters, gchar **values) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (values != NULL); ++ ++ pk_backend_set_uint (self, "search-type", SEARCH_TYPE_DETAILS); ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, pk_backend_search_thread); ++} ++ ++void ++pk_backend_search_files (PkBackend *self, PkBitfield filters, gchar **values) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (values != NULL); ++ ++ /* speed up search by restricting it to local database */ ++ pk_bitfield_add (filters, PK_FILTER_ENUM_INSTALLED); ++ pk_backend_set_uint (self, "filters", filters); ++ ++ pk_backend_set_uint (self, "search-type", SEARCH_TYPE_FILES); ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, pk_backend_search_thread); ++} ++ ++void ++pk_backend_search_groups (PkBackend *self, PkBitfield filters, gchar **values) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (values != NULL); ++ ++ pk_backend_set_uint (self, "search-type", SEARCH_TYPE_GROUP); ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, pk_backend_search_thread); ++} ++ ++void ++pk_backend_search_names (PkBackend *self, PkBitfield filters, gchar **values) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (values != NULL); ++ ++ pk_backend_set_uint (self, "search-type", SEARCH_TYPE_NAME); ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, pk_backend_search_thread); ++} ++ ++void ++pk_backend_what_provides (PkBackend *self, PkBitfield filters, ++ PkProvidesEnum provides, gchar **values) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (values != NULL); ++ ++ pk_backend_set_uint (self, "search-type", SEARCH_TYPE_PROVIDES); ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, pk_backend_search_thread); ++} +diff --git a/backends/alpm/pk-backend-search.h b/backends/alpm/pk-backend-search.h +new file mode 100644 +index 0000000..368965a +--- /dev/null ++++ b/backends/alpm/pk-backend-search.h +@@ -0,0 +1,22 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ +diff --git a/backends/alpm/pk-backend-sync.c b/backends/alpm/pk-backend-sync.c +new file mode 100644 +index 0000000..7147514 +--- /dev/null ++++ b/backends/alpm/pk-backend-sync.c +@@ -0,0 +1,283 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++#include ++ ++#include "pk-backend-alpm.h" ++#include "pk-backend-error.h" ++#include "pk-backend-sync.h" ++#include "pk-backend-transaction.h" ++ ++static gint ++alpm_add_dbtarget (const gchar *repo, const gchar *name) ++{ ++ const alpm_list_t *i; ++ pmpkg_t *pkg; ++ ++ g_return_val_if_fail (repo != NULL, -1); ++ g_return_val_if_fail (name != NULL, -1); ++ ++ for (i = alpm_option_get_syncdbs (); i != NULL; i = i->next) { ++ if (g_strcmp0 (alpm_db_get_name (i->data), repo) == 0) { ++ break; ++ } ++ } ++ ++ if (i == NULL) { ++ pm_errno = PM_ERR_DB_NOT_FOUND; ++ return -1; ++ } ++ ++ pkg = alpm_db_get_pkg (i->data, name); ++ if (pkg == NULL) { ++ pm_errno = PM_ERR_PKG_NOT_FOUND; ++ return -1; ++ } ++ ++ return alpm_add_pkg (pkg); ++} ++ ++static gboolean ++pk_backend_transaction_sync_targets (PkBackend *self, GError **error) ++{ ++ gchar **packages; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ packages = pk_backend_get_strv (self, "package_ids"); ++ ++ g_return_val_if_fail (packages != NULL, FALSE); ++ ++ for (; *packages != NULL; ++packages) { ++ gchar **package = pk_package_id_split (*packages); ++ gchar *repo = package[PK_PACKAGE_ID_DATA]; ++ gchar *name = package[PK_PACKAGE_ID_NAME]; ++ ++ if (alpm_add_dbtarget (repo, name) < 0) { ++ g_set_error (error, ALPM_ERROR, pm_errno, "%s/%s: %s", ++ repo, name, alpm_strerrorlast ()); ++ g_strfreev (package); ++ return FALSE; ++ } ++ ++ g_strfreev (package); ++ } ++ ++ return TRUE; ++} ++ ++static gboolean ++pk_backend_download_packages_thread (PkBackend *self) ++{ ++ alpm_list_t *cachedirs; ++ const gchar *directory; ++ pmtransflag_t flags = 0; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ directory = pk_backend_get_string (self, "directory"); ++ ++ g_return_val_if_fail (directory != NULL, FALSE); ++ ++ /* download files to a PackageKit directory */ ++ cachedirs = alpm_list_strdup (alpm_option_get_cachedirs ()); ++ alpm_option_set_cachedirs (alpm_list_add (NULL, strdup (directory))); ++ ++ flags |= PM_TRANS_FLAG_NODEPS; ++ flags |= PM_TRANS_FLAG_NOCONFLICTS; ++ flags |= PM_TRANS_FLAG_DOWNLOADONLY; ++ ++ if (pk_backend_transaction_initialize (self, flags, &error) && ++ pk_backend_transaction_sync_targets (self, &error) && ++ pk_backend_transaction_simulate (self, &error)) { ++ pk_backend_transaction_commit (self, &error); ++ } ++ ++ alpm_option_set_cachedirs (cachedirs); ++ ++ return pk_backend_transaction_finish (self, error); ++} ++ ++void ++pk_backend_download_packages (PkBackend *self, gchar **package_ids, ++ const gchar *directory) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ g_return_if_fail (directory != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_SETUP, ++ pk_backend_download_packages_thread); ++} ++ ++static gboolean ++pk_backend_simulate_install_packages_thread (PkBackend *self) ++{ ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ if (pk_backend_transaction_initialize (self, 0, &error) && ++ pk_backend_transaction_sync_targets (self, &error) && ++ pk_backend_transaction_simulate (self, &error)) { ++ pk_backend_transaction_packages (self); ++ } ++ ++ return pk_backend_transaction_finish (self, error); ++} ++ ++static gboolean ++pk_backend_install_packages_thread (PkBackend *self) ++{ ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ if (pk_backend_transaction_initialize (self, 0, &error) && ++ pk_backend_transaction_sync_targets (self, &error) && ++ pk_backend_transaction_simulate (self, &error)) { ++ pk_backend_transaction_commit (self, &error); ++ } ++ ++ return pk_backend_transaction_finish (self, error); ++} ++ ++void ++pk_backend_simulate_install_packages (PkBackend *self, gchar **package_ids) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_SETUP, ++ pk_backend_simulate_install_packages_thread); ++} ++ ++void ++pk_backend_install_packages (PkBackend *self, gboolean only_trusted, ++ gchar **package_ids) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_SETUP, ++ pk_backend_install_packages_thread); ++} ++ ++static gboolean ++pk_backend_replaces_dependencies (PkBackend *self, pmpkg_t *pkg) ++{ ++ const alpm_list_t *i, *replaces; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (pkg != NULL, FALSE); ++ ++ replaces = alpm_pkg_get_replaces (pkg); ++ for (i = alpm_trans_get_remove (); i != NULL; i = i->next) { ++ pmpkg_t *rpkg = (pmpkg_t *) i->data; ++ const gchar *rname = alpm_pkg_get_name (rpkg); ++ ++ if (pk_backend_cancelled (self)) { ++ return FALSE; ++ } else if (alpm_list_find_str (replaces, rname) == NULL) { ++ continue; ++ } ++ ++ if (alpm_pkg_get_reason (rpkg) == PM_PKG_REASON_EXPLICIT) { ++ return FALSE; ++ } ++ } ++ ++ return TRUE; ++} ++ ++static gboolean ++pk_backend_update_packages_thread (PkBackend *self) ++{ ++ const alpm_list_t *i; ++ alpm_list_t *asdeps = NULL; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (localdb != NULL, FALSE); ++ ++ if (!pk_backend_transaction_initialize (self, 0, &error) || ++ !pk_backend_transaction_sync_targets (self, &error) || ++ !pk_backend_transaction_simulate (self, &error)) { ++ goto out; ++ } ++ ++ /* change the install reason of packages that replace dependencies */ ++ for (i = alpm_trans_get_add (); i != NULL; i = i->next) { ++ pmpkg_t *pkg = (pmpkg_t *) i->data; ++ const gchar *name = alpm_pkg_get_name (pkg); ++ ++ if (pk_backend_cancelled (self)) { ++ goto out; ++ } else if (alpm_db_get_pkg (localdb, name) != NULL) { ++ continue; ++ } ++ ++ if (pk_backend_replaces_dependencies (self, pkg)) { ++ asdeps = alpm_list_add (asdeps, g_strdup (name)); ++ } ++ } ++ ++ if (!pk_backend_transaction_commit (self, &error)) { ++ goto out; ++ } ++ ++ for (i = asdeps; i != NULL; i = i->next) { ++ const gchar *name = (const gchar *) i->data; ++ alpm_db_set_pkgreason (localdb, name, PM_PKG_REASON_DEPEND); ++ } ++ ++out: ++ alpm_list_free_inner (asdeps, g_free); ++ alpm_list_free (asdeps); ++ ++ return pk_backend_transaction_finish (self, error); ++} ++ ++void ++pk_backend_simulate_update_packages (PkBackend *self, gchar **package_ids) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_SETUP, ++ pk_backend_simulate_install_packages_thread); ++} ++ ++void ++pk_backend_update_packages (PkBackend *self, gboolean only_trusted, ++ gchar **package_ids) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_SETUP, ++ pk_backend_update_packages_thread); ++} +diff --git a/backends/alpm/pk-backend-sync.h b/backends/alpm/pk-backend-sync.h +new file mode 100644 +index 0000000..368965a +--- /dev/null ++++ b/backends/alpm/pk-backend-sync.h +@@ -0,0 +1,22 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ +diff --git a/backends/alpm/pk-backend-transaction.c b/backends/alpm/pk-backend-transaction.c +new file mode 100644 +index 0000000..f919309 +--- /dev/null ++++ b/backends/alpm/pk-backend-transaction.c +@@ -0,0 +1,916 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "pk-backend-alpm.h" ++#include "pk-backend-error.h" ++#include "pk-backend-packages.h" ++#include "pk-backend-transaction.h" ++ ++static off_t dcomplete = 0; ++static off_t dtotal = 0; ++ ++static pmpkg_t *dpkg = NULL; ++static GString *dfiles = NULL; ++ ++static gchar * ++pk_backend_resolve_path (PkBackend *self, const gchar *basename) ++{ ++ const gchar *dirname; ++ ++ g_return_val_if_fail (self != NULL, NULL); ++ g_return_val_if_fail (basename != NULL, NULL); ++ ++ dirname = pk_backend_get_string (self, "directory"); ++ ++ g_return_val_if_fail (dirname != NULL, NULL); ++ ++ return g_build_filename (dirname, basename, NULL); ++} ++ ++static gboolean ++alpm_pkg_has_basename (pmpkg_t *pkg, const gchar *basename) ++{ ++ const alpm_list_t *i; ++ ++ g_return_val_if_fail (pkg != NULL, FALSE); ++ g_return_val_if_fail (basename != NULL, FALSE); ++ ++ if (g_strcmp0 (alpm_pkg_get_filename (pkg), basename) == 0) { ++ return TRUE; ++ } ++ ++ if (alpm_option_get_usedelta () == 0) { ++ return FALSE; ++ } ++ ++ for (i = alpm_pkg_get_deltas (pkg); i != NULL; i = i->next) { ++ const gchar *patch = alpm_delta_get_filename (i->data); ++ ++ if (g_strcmp0 (patch, basename) == 0) { ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++} ++ ++static void ++pk_backend_transaction_download_end (PkBackend *self) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (dpkg != NULL); ++ ++ pk_backend_pkg (self, dpkg, PK_INFO_ENUM_FINISHED); ++ ++ /* tell DownloadPackages what files were downloaded */ ++ if (dfiles != NULL) { ++ gchar *package_id; ++ ++ package_id = alpm_pkg_build_id (dpkg); ++ ++ pk_backend_files (self, package_id, dfiles->str); ++ ++ g_free (package_id); ++ g_string_free (dfiles, TRUE); ++ } ++ ++ dpkg = NULL; ++ dfiles = NULL; ++} ++ ++static void ++pk_backend_transaction_download_start (PkBackend *self, const gchar *basename) ++{ ++ gchar *path; ++ const alpm_list_t *i; ++ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (basename != NULL); ++ ++ /* continue or finish downloading the current package */ ++ if (dpkg != NULL) { ++ if (alpm_pkg_has_basename (dpkg, basename)) { ++ if (dfiles != NULL) { ++ path = pk_backend_resolve_path (self, basename); ++ g_string_append_printf (dfiles, ";%s", path); ++ g_free (path); ++ } ++ ++ return; ++ } else { ++ pk_backend_transaction_download_end (self); ++ dpkg = NULL; ++ } ++ } ++ ++ /* figure out what the next package is */ ++ for (i = alpm_trans_get_add (); i != NULL; i = i->next) { ++ pmpkg_t *pkg = (pmpkg_t *) i->data; ++ ++ if (alpm_pkg_has_basename (pkg, basename)) { ++ dpkg = pkg; ++ break; ++ } ++ } ++ ++ if (dpkg == NULL) { ++ return; ++ } ++ ++ pk_backend_pkg (self, dpkg, PK_INFO_ENUM_DOWNLOADING); ++ ++ /* start collecting files for the new package */ ++ if (pk_backend_get_role (self) == PK_ROLE_ENUM_DOWNLOAD_PACKAGES) { ++ path = pk_backend_resolve_path (self, basename); ++ dfiles = g_string_new (path); ++ g_free (path); ++ } ++} ++ ++static void ++pk_backend_transaction_totaldlcb (off_t total) ++{ ++ g_return_if_fail (backend != NULL); ++ ++ if (dtotal > 0 && dpkg != NULL) { ++ pk_backend_transaction_download_end (backend); ++ } ++ ++ dcomplete = 0; ++ dtotal = total; ++} ++ ++static void ++pk_backend_transaction_dlcb (const gchar *basename, off_t complete, off_t total) ++{ ++ guint percentage = 100, sub_percentage = 100; ++ ++ g_return_if_fail (basename != NULL); ++ g_return_if_fail (complete <= total); ++ g_return_if_fail (backend != NULL); ++ ++ if (total > 0) { ++ sub_percentage = complete * 100 / total; ++ } ++ ++ if (dtotal > 0) { ++ percentage = (dcomplete + complete) * 100 / dtotal; ++ } else if (dtotal < 0) { ++ /* database files */ ++ percentage = (dcomplete * 100 + sub_percentage) / -dtotal; ++ ++ if (complete == total) { ++ complete = total = 1; ++ } else { ++ complete = total + 1; ++ } ++ } ++ ++ if (complete == 0) { ++ g_debug ("downloading file %s", basename); ++ pk_backend_set_status (backend, PK_STATUS_ENUM_DOWNLOAD); ++ pk_backend_transaction_download_start (backend, basename); ++ } else if (complete == total) { ++ dcomplete += complete; ++ } ++ ++ pk_backend_set_sub_percentage (backend, sub_percentage); ++ pk_backend_set_percentage (backend, percentage); ++} ++ ++static void ++pk_backend_transaction_progress_cb (pmtransprog_t type, const gchar *target, ++ gint percent, gsize targets, gsize current) ++{ ++ static gint recent = 101; ++ gsize overall = percent + (current - 1) * 100; ++ ++ /* TODO: revert when fixed upstream */ ++ if (type == PM_TRANS_PROGRESS_CONFLICTS_START || ++ type == PM_TRANS_PROGRESS_DISKSPACE_START || ++ type == PM_TRANS_PROGRESS_INTEGRITY_START) { ++ if (current < targets) { ++ overall = percent + current++ * 100; ++ } ++ } ++ ++ if (current < 1 || targets < current) { ++ g_warning ("TODO: CURRENT/TARGETS FAILED for %d", type); ++ } ++ ++ g_return_if_fail (target != NULL); ++ g_return_if_fail (0 <= percent && percent <= 100); ++ g_return_if_fail (1 <= current && current <= targets); ++ g_return_if_fail (backend != NULL); ++ ++ /* update transaction progress */ ++ switch (type) { ++ case PM_TRANS_PROGRESS_ADD_START: ++ case PM_TRANS_PROGRESS_UPGRADE_START: ++ case PM_TRANS_PROGRESS_REMOVE_START: ++ case PM_TRANS_PROGRESS_CONFLICTS_START: ++ case PM_TRANS_PROGRESS_DISKSPACE_START: ++ case PM_TRANS_PROGRESS_INTEGRITY_START: ++ if (percent == recent) { ++ break; ++ } ++ ++ pk_backend_set_sub_percentage (backend, percent); ++ pk_backend_set_percentage (backend, overall / targets); ++ recent = percent; ++ ++ g_debug ("%d%% of %s complete (%zu of %zu)", percent, ++ target, current, targets); ++ break; ++ ++ default: ++ g_warning ("unknown progress type %d", type); ++ break; ++ } ++} ++ ++static void ++pk_backend_install_ignorepkg (PkBackend *self, pmpkg_t *pkg, gint *result) ++{ ++ gchar *output; ++ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (pkg != NULL); ++ g_return_if_fail (result != NULL); ++ ++ switch (pk_backend_get_role (self)) { ++ case PK_ROLE_ENUM_INSTALL_PACKAGES: ++ output = g_strdup_printf ("%s: was not ignored\n", ++ alpm_pkg_get_name (pkg)); ++ pk_backend_output (self, output); ++ g_free (output); ++ ++ case PK_ROLE_ENUM_DOWNLOAD_PACKAGES: ++ case PK_ROLE_ENUM_SIMULATE_INSTALL_PACKAGES: ++ *result = 1; ++ break; ++ ++ default: ++ *result = 0; ++ break; ++ } ++} ++ ++static void ++pk_backend_select_provider (PkBackend *self, pmdepend_t *dep, ++ const alpm_list_t *providers) ++{ ++ gchar *output; ++ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (dep != NULL); ++ g_return_if_fail (providers != NULL); ++ ++ output = g_strdup_printf ("provider package was selected " ++ "(%s provides %s)\n", ++ alpm_pkg_get_name (providers->data), ++ alpm_dep_get_name (dep)); ++ pk_backend_output (self, output); ++ g_free (output); ++} ++ ++static void ++pk_backend_transaction_conv_cb (pmtransconv_t question, gpointer data1, ++ gpointer data2, gpointer data3, gint *result) ++{ ++ g_return_if_fail (result != NULL); ++ g_return_if_fail (backend != NULL); ++ ++ switch (question) { ++ case PM_TRANS_CONV_INSTALL_IGNOREPKG: ++ pk_backend_install_ignorepkg (backend, data1, result); ++ break; ++ ++ case PM_TRANS_CONV_REPLACE_PKG: ++ case PM_TRANS_CONV_CONFLICT_PKG: ++ case PM_TRANS_CONV_CORRUPTED_PKG: ++ case PM_TRANS_CONV_LOCAL_NEWER: ++ /* these actions are mostly harmless */ ++ g_debug ("safe question %d", question); ++ *result = 1; ++ break; ++ ++ case PM_TRANS_CONV_REMOVE_PKGS: ++ g_debug ("unsafe question %d", question); ++ *result = 0; ++ break; ++ ++ case PM_TRANS_CONV_SELECT_PROVIDER: ++ pk_backend_select_provider (backend, data1, data2); ++ *result = 0; ++ break; ++ ++ default: ++ g_warning ("unknown question %d", question); ++ break; ++ } ++} ++ ++static void ++pk_backend_transaction_dep_resolve (PkBackend *self) ++{ ++ g_return_if_fail (self != NULL); ++ ++ pk_backend_set_status (self, PK_STATUS_ENUM_DEP_RESOLVE); ++} ++ ++static void ++pk_backend_transaction_test_commit (PkBackend *self) ++{ ++ g_return_if_fail (self != NULL); ++ ++ pk_backend_set_status (self, PK_STATUS_ENUM_TEST_COMMIT); ++} ++ ++static void ++pk_backend_transaction_add_start (PkBackend *self, pmpkg_t *pkg) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (pkg != NULL); ++ ++ pk_backend_set_status (self, PK_STATUS_ENUM_INSTALL); ++ pk_backend_pkg (self, pkg, PK_INFO_ENUM_INSTALLING); ++} ++ ++static void ++pk_backend_transaction_add_done (PkBackend *self, pmpkg_t *pkg) ++{ ++ const gchar *name, *version; ++ const alpm_list_t *i, *optdepends; ++ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (pkg != NULL); ++ ++ name = alpm_pkg_get_name (pkg); ++ version = alpm_pkg_get_version (pkg); ++ ++ alpm_logaction ("installed %s (%s)\n", name, version); ++ pk_backend_pkg (self, pkg, PK_INFO_ENUM_FINISHED); ++ ++ optdepends = alpm_pkg_get_optdepends (pkg); ++ if (optdepends != NULL) { ++ GString *depends = g_string_new (""); ++ ++ g_string_append_printf (depends, ++ "Optional dependencies for %s:\n", ++ name); ++ ++ for (i = optdepends; i != NULL; i = i->next) { ++ g_string_append_printf (depends, "%s\n", ++ (const gchar *) i->data); ++ } ++ ++ pk_backend_output (self, depends->str); ++ g_string_free (depends, TRUE); ++ } ++} ++ ++static void ++pk_backend_transaction_remove_start (PkBackend *self, pmpkg_t *pkg) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (pkg != NULL); ++ ++ pk_backend_set_status (self, PK_STATUS_ENUM_REMOVE); ++ pk_backend_pkg (self, pkg, PK_INFO_ENUM_REMOVING); ++} ++ ++static void ++pk_backend_transaction_remove_done (PkBackend *self, pmpkg_t *pkg) ++{ ++ const gchar *name, *version; ++ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (pkg != NULL); ++ ++ name = alpm_pkg_get_name (pkg); ++ version = alpm_pkg_get_version (pkg); ++ ++ alpm_logaction ("removed %s (%s)\n", name, version); ++ pk_backend_pkg (self, pkg, PK_INFO_ENUM_FINISHED); ++} ++ ++static void ++pk_backend_transaction_upgrade_start (PkBackend *self, pmpkg_t *pkg, ++ pmpkg_t *old) ++{ ++ PkRoleEnum role; ++ PkStatusEnum state; ++ PkInfoEnum info; ++ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (pkg != NULL); ++ ++ role = pk_backend_get_role (self); ++ if (role == PK_ROLE_ENUM_INSTALL_FILES || ++ role == PK_ROLE_ENUM_SIMULATE_INSTALL_FILES) { ++ state = PK_STATUS_ENUM_INSTALL; ++ info = PK_INFO_ENUM_INSTALLING; ++ } else { ++ state = PK_STATUS_ENUM_UPDATE; ++ info = PK_INFO_ENUM_UPDATING; ++ } ++ ++ pk_backend_set_status (self, state); ++ pk_backend_pkg (self, pkg, info); ++} ++ ++static void ++pk_backend_transaction_upgrade_done (PkBackend *self, pmpkg_t *pkg, ++ pmpkg_t *old) ++{ ++ const gchar *name, *pre, *post; ++ const alpm_list_t *i; ++ alpm_list_t *optdepends; ++ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (pkg != NULL); ++ g_return_if_fail (old != NULL); ++ ++ name = alpm_pkg_get_name (pkg); ++ pre = alpm_pkg_get_version (old); ++ post = alpm_pkg_get_version (pkg); ++ ++ alpm_logaction ("upgraded %s (%s -> %s)\n", name, pre, post); ++ pk_backend_pkg (self, pkg, PK_INFO_ENUM_FINISHED); ++ ++ optdepends = alpm_list_diff (alpm_pkg_get_optdepends (pkg), ++ alpm_pkg_get_optdepends (old), ++ (alpm_list_fn_cmp) g_strcmp0); ++ if (optdepends != NULL) { ++ GString *depends = g_string_new (""); ++ ++ g_string_append_printf (depends, ++ "New optional dependencies for %s\n", ++ name); ++ ++ for (i = optdepends; i != NULL; i = i->next) { ++ g_string_append_printf (depends, "%s\n", ++ (const gchar *) i->data); ++ } ++ ++ pk_backend_output (self, depends->str); ++ ++ g_string_free (depends, TRUE); ++ alpm_list_free (optdepends); ++ } ++} ++ ++static void ++pk_backend_transaction_event_cb (pmtransevt_t event, gpointer data, ++ gpointer old) ++{ ++ g_return_if_fail (backend != NULL); ++ ++ /* figure out the backend status and package info */ ++ switch (event) { ++ case PM_TRANS_EVT_CHECKDEPS_START: ++ case PM_TRANS_EVT_RESOLVEDEPS_START: ++ pk_backend_transaction_dep_resolve (backend); ++ break; ++ ++ case PM_TRANS_EVT_FILECONFLICTS_START: ++ case PM_TRANS_EVT_INTERCONFLICTS_START: ++ case PM_TRANS_EVT_INTEGRITY_START: ++ case PM_TRANS_EVT_DELTA_INTEGRITY_START: ++ case PM_TRANS_EVT_DISKSPACE_START: ++ pk_backend_transaction_test_commit (backend); ++ break; ++ ++ case PM_TRANS_EVT_ADD_START: ++ pk_backend_transaction_add_start (backend, data); ++ break; ++ ++ case PM_TRANS_EVT_ADD_DONE: ++ pk_backend_transaction_add_done (backend, data); ++ break; ++ ++ case PM_TRANS_EVT_REMOVE_START: ++ pk_backend_transaction_remove_start (backend, data); ++ break; ++ ++ case PM_TRANS_EVT_REMOVE_DONE: ++ pk_backend_transaction_remove_done (backend, data); ++ break; ++ ++ case PM_TRANS_EVT_UPGRADE_START: ++ pk_backend_transaction_upgrade_start (backend, data, ++ old); ++ break; ++ ++ case PM_TRANS_EVT_UPGRADE_DONE: ++ pk_backend_transaction_upgrade_done (backend, data, ++ old); ++ break; ++ ++ case PM_TRANS_EVT_SCRIPTLET_INFO: ++ pk_backend_output (backend, data); ++ break; ++ ++ default: ++ g_debug ("unhandled event %d", event); ++ break; ++ } ++} ++ ++static void ++transaction_cancelled_cb (GCancellable *object, gpointer data) ++{ ++ g_return_if_fail (data != NULL); ++ ++ alpm_trans_interrupt (); ++} ++ ++gboolean ++pk_backend_transaction_initialize (PkBackend *self, pmtransflag_t flags, ++ GError **error) ++{ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (cancellable != NULL, FALSE); ++ ++ if (alpm_trans_init (flags, pk_backend_transaction_event_cb, ++ pk_backend_transaction_conv_cb, ++ pk_backend_transaction_progress_cb) < 0) { ++ g_set_error_literal (error, ALPM_ERROR, pm_errno, ++ alpm_strerrorlast ()); ++ return FALSE; ++ } ++ ++ alpm_option_set_dlcb (pk_backend_transaction_dlcb); ++ alpm_option_set_totaldlcb (pk_backend_transaction_totaldlcb); ++ ++ g_cancellable_connect (cancellable, ++ G_CALLBACK (transaction_cancelled_cb), ++ self, NULL); ++ ++ return TRUE; ++} ++ ++static gchar * ++alpm_pkg_build_list (const alpm_list_t *i) ++{ ++ GString *list; ++ ++ if (i == NULL) { ++ return NULL; ++ } else { ++ list = g_string_new (""); ++ } ++ ++ for (; i != NULL; i = i->next) { ++ g_string_append_printf (list, "%s, ", ++ alpm_pkg_get_name (i->data)); ++ } ++ ++ g_string_truncate (list, list->len - 2); ++ return g_string_free (list, FALSE); ++} ++ ++static gchar * ++alpm_miss_build_list (const alpm_list_t *i) ++{ ++ GString *list; ++ ++ if (i == NULL) { ++ return NULL; ++ } else { ++ list = g_string_new (""); ++ } ++ ++ for (; i != NULL; i = i->next) { ++ pmdepend_t *dep = alpm_miss_get_dep (i->data); ++ gchar *depend = alpm_dep_compute_string (dep); ++ g_string_append_printf (list, "%s <- %s, ", depend, ++ alpm_miss_get_target (i->data)); ++ free (depend); ++ } ++ ++ g_string_truncate (list, list->len - 2); ++ return g_string_free (list, FALSE); ++} ++ ++static void ++alpm_dep_free (gpointer dep) ++{ ++ /* TODO: remove when implemented in libalpm */ ++ free ((gpointer) alpm_dep_get_name (dep)); ++ free ((gpointer) alpm_dep_get_version (dep)); ++ free (dep); ++} ++ ++static void ++alpm_miss_free (gpointer miss) ++{ ++ /* TODO: remove when implemented in libalpm */ ++ const gchar *temp = alpm_miss_get_causingpkg (miss); ++ if (temp != NULL) { ++ free ((gpointer) temp); ++ } ++ ++ free ((gpointer) alpm_miss_get_target (miss)); ++ alpm_dep_free (alpm_miss_get_dep (miss)); ++ free (miss); ++} ++ ++static gchar * ++alpm_conflict_build_list (const alpm_list_t *i) ++{ ++ GString *list; ++ ++ if (i == NULL) { ++ return NULL; ++ } else { ++ list = g_string_new (""); ++ } ++ ++ for (; i != NULL; i = i->next) { ++ const gchar *first = alpm_conflict_get_package1 (i->data); ++ const gchar *second = alpm_conflict_get_package2 (i->data); ++ const gchar *reason = alpm_conflict_get_reason (i->data); ++ ++ if (g_strcmp0 (first, reason) == 0 || ++ g_strcmp0 (second, reason) == 0) { ++ g_string_append_printf (list, "%s <-> %s, ", first, ++ second); ++ } else { ++ g_string_append_printf (list, "%s <-> %s (%s), ", first, ++ second, reason); ++ } ++ } ++ ++ g_string_truncate (list, list->len - 2); ++ return g_string_free (list, FALSE); ++} ++ ++static void ++alpm_conflict_free (gpointer conflict) ++{ ++ /* TODO: remove when implemented in libalpm */ ++ free ((gpointer) alpm_conflict_get_package1 (conflict)); ++ free ((gpointer) alpm_conflict_get_package2 (conflict)); ++ free ((gpointer) alpm_conflict_get_reason (conflict)); ++ free (conflict); ++} ++ ++static gchar * ++alpm_fileconflict_build_list (const alpm_list_t *i) ++{ ++ GString *list; ++ ++ if (i == NULL) { ++ return NULL; ++ } else { ++ list = g_string_new (""); ++ } ++ ++ for (; i != NULL; i = i->next) { ++ const gchar *target = alpm_fileconflict_get_target (i->data); ++ const gchar *file = alpm_fileconflict_get_file (i->data); ++ const gchar *ctarget = alpm_fileconflict_get_ctarget (i->data); ++ if (*ctarget != '\0') { ++ g_string_append_printf (list, "%s <-> %s (%s), ", ++ target, ctarget, file); ++ } else { ++ g_string_append_printf (list, "%s (%s), ", target, ++ file); ++ } ++ } ++ ++ g_string_truncate (list, list->len - 2); ++ return g_string_free (list, FALSE); ++} ++ ++static void ++alpm_fileconflict_free (gpointer conflict) ++{ ++ /* TODO: remove when implemented in libalpm */ ++ const gchar *temp = alpm_fileconflict_get_ctarget (conflict); ++ if (*temp != '\0') { ++ free ((gpointer) temp); ++ } ++ ++ free ((gpointer) alpm_fileconflict_get_target (conflict)); ++ free ((gpointer) alpm_fileconflict_get_file (conflict)); ++ free (conflict); ++} ++ ++gboolean ++pk_backend_transaction_simulate (PkBackend *self, GError **error) ++{ ++ alpm_list_t *data = NULL; ++ gchar *prefix; ++ ++ if (alpm_trans_prepare (&data) >= 0) { ++ return TRUE; ++ } ++ ++ switch (pm_errno) { ++ case PM_ERR_PKG_INVALID_ARCH: ++ prefix = alpm_pkg_build_list (data); ++ alpm_list_free (data); ++ break; ++ ++ case PM_ERR_UNSATISFIED_DEPS: ++ prefix = alpm_miss_build_list (data); ++ alpm_list_free_inner (data, alpm_miss_free); ++ alpm_list_free (data); ++ break; ++ ++ case PM_ERR_CONFLICTING_DEPS: ++ prefix = alpm_conflict_build_list (data); ++ alpm_list_free_inner (data, alpm_conflict_free); ++ alpm_list_free (data); ++ break; ++ ++ case PM_ERR_FILE_CONFLICTS: ++ prefix = alpm_fileconflict_build_list (data); ++ alpm_list_free_inner (data, alpm_fileconflict_free); ++ alpm_list_free (data); ++ break; ++ ++ default: ++ prefix = NULL; ++ if (data != NULL) { ++ g_warning ("unhandled error %d", pm_errno); ++ } ++ break; ++ } ++ ++ if (prefix != NULL) { ++ g_set_error (error, ALPM_ERROR, pm_errno, "%s: %s", prefix, ++ alpm_strerrorlast ()); ++ g_free (prefix); ++ } else { ++ g_set_error_literal (error, ALPM_ERROR, pm_errno, ++ alpm_strerrorlast ()); ++ } ++ ++ return FALSE; ++} ++ ++void ++pk_backend_transaction_packages (PkBackend *self) ++{ ++ const alpm_list_t *i; ++ PkInfoEnum info; ++ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (localdb != NULL); ++ ++ /* emit packages that would have been installed */ ++ for (i = alpm_trans_get_add (); i != NULL; i = i->next) { ++ if (pk_backend_cancelled (self)) { ++ break; ++ } else { ++ const gchar *name = alpm_pkg_get_name (i->data); ++ ++ if (alpm_db_get_pkg (localdb, name) != NULL) { ++ info = PK_INFO_ENUM_UPDATING; ++ } else { ++ info = PK_INFO_ENUM_INSTALLING; ++ } ++ ++ pk_backend_pkg (self, i->data, info); ++ } ++ } ++ ++ switch (pk_backend_get_role (self)) { ++ case PK_ROLE_ENUM_SIMULATE_UPDATE_PACKAGES: ++ info = PK_INFO_ENUM_OBSOLETING; ++ break; ++ ++ default: ++ info = PK_INFO_ENUM_REMOVING; ++ break; ++ } ++ ++ /* emit packages that would have been removed */ ++ for (i = alpm_trans_get_remove (); i != NULL; i = i->next) { ++ if (pk_backend_cancelled (self)) { ++ break; ++ } else { ++ pk_backend_pkg (self, i->data, info); ++ } ++ } ++} ++ ++static gchar * ++alpm_string_build_list (const alpm_list_t *i) ++{ ++ GString *list; ++ ++ if (i == NULL) { ++ return NULL; ++ } else { ++ list = g_string_new (""); ++ } ++ ++ for (; i != NULL; i = i->next) { ++ g_string_append_printf (list, "%s, ", (const gchar *) i->data); ++ } ++ ++ g_string_truncate (list, list->len - 2); ++ return g_string_free (list, FALSE); ++} ++ ++gboolean ++pk_backend_transaction_commit (PkBackend *self, GError **error) ++{ ++ alpm_list_t *data = NULL; ++ gchar *prefix; ++ ++ if (pk_backend_cancelled (self)) { ++ return TRUE; ++ } ++ ++ pk_backend_set_allow_cancel (self, FALSE); ++ pk_backend_set_status (self, PK_STATUS_ENUM_RUNNING); ++ ++ if (alpm_trans_commit (&data) >= 0) { ++ return TRUE; ++ } ++ ++ switch (pm_errno) { ++ case PM_ERR_FILE_CONFLICTS: ++ prefix = alpm_fileconflict_build_list (data); ++ alpm_list_free_inner (data, alpm_fileconflict_free); ++ alpm_list_free (data); ++ break; ++ ++ case PM_ERR_PKG_INVALID: ++ case PM_ERR_DLT_INVALID: ++ prefix = alpm_string_build_list (data); ++ alpm_list_free (data); ++ break; ++ ++ default: ++ prefix = NULL; ++ if (data != NULL) { ++ g_warning ("unhandled error %d", pm_errno); ++ } ++ break; ++ } ++ ++ if (prefix != NULL) { ++ g_set_error (error, ALPM_ERROR, pm_errno, "%s: %s", prefix, ++ alpm_strerrorlast ()); ++ g_free (prefix); ++ } else { ++ g_set_error_literal (error, ALPM_ERROR, pm_errno, ++ alpm_strerrorlast ()); ++ } ++ ++ return FALSE; ++} ++ ++gboolean ++pk_backend_transaction_end (PkBackend *self, GError **error) ++{ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ alpm_option_set_dlcb (NULL); ++ alpm_option_set_totaldlcb (NULL); ++ ++ if (alpm_trans_release () < 0) { ++ g_set_error_literal (error, ALPM_ERROR, pm_errno, ++ alpm_strerrorlast ()); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++gboolean ++pk_backend_transaction_finish (PkBackend *self, GError *error) ++{ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ pk_backend_transaction_end (self, (error == NULL) ? &error : NULL); ++ ++ return pk_backend_finish (self, error); ++} +diff --git a/backends/alpm/pk-backend-transaction.h b/backends/alpm/pk-backend-transaction.h +new file mode 100644 +index 0000000..7bc1af0 +--- /dev/null ++++ b/backends/alpm/pk-backend-transaction.h +@@ -0,0 +1,43 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++ ++gboolean pk_backend_transaction_initialize (PkBackend *self, ++ pmtransflag_t flags, ++ GError **error); ++ ++gboolean pk_backend_transaction_simulate (PkBackend *self, ++ GError **error); ++ ++void pk_backend_transaction_packages (PkBackend *self); ++ ++gboolean pk_backend_transaction_commit (PkBackend *self, ++ GError **error); ++ ++gboolean pk_backend_transaction_end (PkBackend *self, ++ GError **error); ++ ++gboolean pk_backend_transaction_finish (PkBackend *self, ++ GError *error); +diff --git a/backends/alpm/pk-backend-update.c b/backends/alpm/pk-backend-update.c +new file mode 100644 +index 0000000..a281953 +--- /dev/null ++++ b/backends/alpm/pk-backend-update.c +@@ -0,0 +1,443 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "pk-backend-alpm.h" ++#include "pk-backend-error.h" ++#include "pk-backend-packages.h" ++#include "pk-backend-transaction.h" ++#include "pk-backend-update.h" ++ ++static gchar * ++alpm_pkg_build_replaces (pmpkg_t *pkg) ++{ ++ const alpm_list_t *i; ++ GString *string = NULL; ++ ++ g_return_val_if_fail (pkg != NULL, NULL); ++ g_return_val_if_fail (localdb != NULL, NULL); ++ ++ /* make a list of the packages that package replaces */ ++ for (i = alpm_pkg_get_replaces (pkg); i != NULL; i = i->next) { ++ pmpkg_t *replaces = alpm_db_get_pkg (localdb, i->data); ++ ++ if (replaces != NULL) { ++ gchar *package = alpm_pkg_build_id (replaces); ++ if (string == NULL) { ++ string = g_string_new (package); ++ } else { ++ g_string_append_printf (string, "&%s", package); ++ } ++ g_free (package); ++ } ++ } ++ ++ if (string != NULL) { ++ return g_string_free (string, FALSE); ++ } else { ++ return NULL; ++ } ++} ++ ++static gchar * ++alpm_pkg_build_urls (pmpkg_t *pkg) ++{ ++ GString *string = g_string_new (""); ++#ifdef ALPM_PACKAGE_URL ++ const gchar *name, *arch, *repo, *url; ++#else ++ const gchar *url; ++#endif ++ ++ g_return_val_if_fail (pkg != NULL, NULL); ++ ++ /* grab the URL of the package... */ ++ url = alpm_pkg_get_url (pkg); ++ if (url != NULL) { ++ g_string_append_printf (string, "%s;Package website;", url); ++ } ++ ++#ifdef ALPM_PACKAGE_URL ++ /* ... and construct the distro URL if possible */ ++ name = alpm_pkg_get_name (pkg); ++ arch = alpm_pkg_get_arch (pkg); ++ repo = alpm_db_get_name (alpm_pkg_get_db (pkg)); ++ ++ g_string_append_printf (string, ALPM_PACKAGE_URL ";Distribution page;", ++ repo, arch, name); ++#endif ++ ++ g_string_truncate (string, string->len - 1); ++ return g_string_free (string, FALSE); ++} ++ ++static gboolean ++alpm_pkg_same_pkgver (pmpkg_t *a, pmpkg_t *b) ++{ ++ const gchar *version_a, *version_b, *last_a, *last_b; ++ gsize length_a, length_b; ++ ++ g_return_val_if_fail (a != NULL, (b == NULL)); ++ g_return_val_if_fail (b != NULL, FALSE); ++ ++ version_a = alpm_pkg_get_version (a); ++ version_b = alpm_pkg_get_version (b); ++ ++ last_a = strrchr (version_a, '-'); ++ last_b = strrchr (version_b, '-'); ++ ++ if (last_a != NULL) { ++ length_a = last_a - version_a; ++ } else { ++ length_a = strlen (version_a); ++ } ++ ++ if (last_b != NULL) { ++ length_b = last_b - version_b; ++ } else { ++ length_b = strlen (version_b); ++ } ++ ++ if (length_a != length_b) { ++ return FALSE; ++ } else { ++ return strncmp (version_a, version_b, length_a) == 0; ++ } ++} ++ ++static gboolean ++pk_backend_get_update_detail_thread (PkBackend *self) ++{ ++ gchar **packages; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (localdb != NULL, FALSE); ++ ++ packages = pk_backend_get_strv (self, "package_ids"); ++ ++ g_return_val_if_fail (packages != NULL, FALSE); ++ ++ /* collect details about updates */ ++ for (; *packages != NULL; ++packages) { ++ pmpkg_t *pkg, *old; ++ pmdb_t *db; ++ ++ gchar *upgrades, *replaces, *urls; ++ const gchar *reason; ++ ++ PkRestartEnum restart; ++ PkUpdateStateEnum state; ++ ++ GTimeVal built = { 0 }, installed = { 0 }; ++ gchar *issued, *updated; ++ ++ if (pk_backend_cancelled (self)) { ++ break; ++ } ++ ++ pkg = pk_backend_find_pkg (self, *packages, &error); ++ if (pkg == NULL) { ++ break; ++ } ++ ++ old = alpm_db_get_pkg (localdb, alpm_pkg_get_name (pkg)); ++ if (old != NULL) { ++ upgrades = alpm_pkg_build_id (old); ++ if (alpm_pkg_same_pkgver (pkg, old)) { ++ reason = "Update to a newer release"; ++ } else { ++ reason = "Update to a new upstream version"; ++ } ++ } else { ++ upgrades = NULL; ++ reason = "Install to replace an older package"; ++ } ++ ++ db = alpm_pkg_get_db (pkg); ++ replaces = alpm_pkg_build_replaces (pkg); ++ urls = alpm_pkg_build_urls (pkg); ++ ++ if (g_str_has_prefix (alpm_pkg_get_name (pkg), "kernel")) { ++ restart = PK_RESTART_ENUM_SYSTEM; ++ } else { ++ restart = PK_RESTART_ENUM_NONE; ++ } ++ ++ if (g_str_has_suffix (alpm_db_get_name (db), "testing")) { ++ state = PK_UPDATE_STATE_ENUM_TESTING; ++ } else { ++ state = PK_UPDATE_STATE_ENUM_STABLE; ++ } ++ ++ built.tv_sec = alpm_pkg_get_builddate (pkg); ++ if (built.tv_sec > 0) { ++ issued = g_time_val_to_iso8601 (&built); ++ } else { ++ issued = NULL; ++ } ++ ++ if (upgrades != NULL) { ++ installed.tv_sec = alpm_pkg_get_installdate (old); ++ if (installed.tv_sec > 0) { ++ updated = g_time_val_to_iso8601 (&installed); ++ } else { ++ updated = NULL; ++ } ++ } else { ++ updated = NULL; ++ } ++ ++ pk_backend_update_detail (self, *packages, upgrades, replaces, ++ urls, NULL, NULL, restart, reason, ++ NULL, state, issued, updated); ++ ++ g_free (issued); ++ g_free (updated); ++ ++ g_free (urls); ++ g_free (replaces); ++ g_free (upgrades); ++ } ++ ++ return pk_backend_finish (self, error); ++} ++ ++void ++pk_backend_get_update_detail (PkBackend *self, gchar **package_ids) ++{ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (package_ids != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, ++ pk_backend_get_update_detail_thread); ++} ++ ++static gboolean ++pk_backend_update_databases (PkBackend *self, gint force, GError **error) { ++ alpm_cb_download dlcb; ++ alpm_cb_totaldl totaldlcb; ++ const alpm_list_t *i; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ if (!pk_backend_transaction_initialize (self, 0, error)) { ++ return FALSE; ++ } ++ ++ alpm_logaction ("synchronizing package lists\n"); ++ ++ dlcb = alpm_option_get_dlcb (); ++ totaldlcb = alpm_option_get_totaldlcb (); ++ ++ /* set total size to minus the number of databases */ ++ i = alpm_option_get_syncdbs (); ++ totaldlcb (-alpm_list_count (i)); ++ ++ for (; i != NULL; i = i->next) { ++ gint result; ++ ++ if (pk_backend_cancelled (self)) { ++ /* pretend to be finished */ ++ i = NULL; ++ break; ++ } ++ ++ result = alpm_db_update (force, i->data); ++ ++ if (result > 0) { ++ /* fake the download when already up to date */ ++ dlcb ("", 1, 1); ++ } else if (result < 0) { ++ g_set_error (error, ALPM_ERROR, pm_errno, "[%s]: %s", ++ alpm_db_get_name (i->data), ++ alpm_strerrorlast ()); ++ break; ++ } ++ } ++ ++ totaldlcb (0); ++ ++ if (i == NULL) { ++ return pk_backend_transaction_end (self, error); ++ } else { ++ pk_backend_transaction_end (self, NULL); ++ return FALSE; ++ } ++} ++ ++static gboolean ++alpm_pkg_is_ignorepkg (pmpkg_t *pkg) ++{ ++ const alpm_list_t *ignorepkgs, *ignoregrps, *i; ++ ++ g_return_val_if_fail (pkg != NULL, TRUE); ++ ++ ignorepkgs = alpm_option_get_ignorepkgs (); ++ if (alpm_list_find_str (ignorepkgs, alpm_pkg_get_name (pkg)) != NULL) { ++ return TRUE; ++ } ++ ++ ignoregrps = alpm_option_get_ignoregrps (); ++ for (i = alpm_pkg_get_groups (pkg); i != NULL; i = i->next) { ++ if (alpm_list_find_str (ignoregrps, i->data) != NULL) { ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++} ++ ++static gboolean ++alpm_pkg_is_syncfirst (pmpkg_t *pkg) ++{ ++ g_return_val_if_fail (pkg != NULL, FALSE); ++ ++ if (alpm_list_find_str (syncfirsts, alpm_pkg_get_name (pkg)) != NULL) { ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++static pmpkg_t * ++alpm_pkg_find_update (pmpkg_t *pkg, const alpm_list_t *dbs) ++{ ++ const gchar *name; ++ const alpm_list_t *i; ++ ++ g_return_val_if_fail (pkg != NULL, NULL); ++ ++ name = alpm_pkg_get_name (pkg); ++ ++ for (; dbs != NULL; dbs = dbs->next) { ++ pmpkg_t *update = alpm_db_get_pkg (dbs->data, name); ++ ++ if (update != NULL) { ++ if (alpm_pkg_vercmp (alpm_pkg_get_version (update), ++ alpm_pkg_get_version (pkg)) > 0) { ++ return update; ++ } else { ++ return NULL; ++ } ++ } ++ ++ i = alpm_db_get_pkgcache (dbs->data); ++ for (; i != NULL; i = i->next) { ++ if (alpm_list_find_str (alpm_pkg_get_replaces (i->data), ++ name) != NULL) { ++ return i->data; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++static gboolean ++pk_backend_get_updates_thread (PkBackend *self) ++{ ++ struct stat cache; ++ time_t one_hour_ago; ++ const alpm_list_t *i, *syncdbs; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ g_return_val_if_fail (localdb != NULL, FALSE); ++ ++ time (&one_hour_ago); ++ one_hour_ago -= 60 * 60; ++ ++ /* refresh databases if they are older than an hour */ ++ if (g_stat (ALPM_CACHE_PATH, &cache) < 0 || ++ cache.st_mtime < one_hour_ago) { ++ GError *error = NULL; ++ /* show updates even if the databases could not be updated */ ++ if (!pk_backend_update_databases (self, 0, &error)) { ++ g_warning ("%s", error->message); ++ } ++ } else { ++ g_debug ("databases have been refreshed recently"); ++ } ++ ++ /* find outdated and replacement packages */ ++ syncdbs = alpm_option_get_syncdbs (); ++ for (i = alpm_db_get_pkgcache (localdb); i != NULL; i = i->next) { ++ pmpkg_t *upgrade = alpm_pkg_find_update (i->data, syncdbs); ++ ++ if (pk_backend_cancelled (self)) { ++ break; ++ } else if (upgrade != NULL) { ++ PkInfoEnum info; ++ ++ if (alpm_pkg_is_ignorepkg (upgrade)) { ++ info = PK_INFO_ENUM_BLOCKED; ++ } else if (alpm_pkg_is_syncfirst (upgrade)) { ++ info = PK_INFO_ENUM_IMPORTANT; ++ } else { ++ info = PK_INFO_ENUM_NORMAL; ++ } ++ ++ pk_backend_pkg (self, upgrade, info); ++ } ++ } ++ ++ return pk_backend_finish (self, NULL); ++} ++ ++void ++pk_backend_get_updates (PkBackend *self, PkBitfield filters) ++{ ++ g_return_if_fail (self != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_QUERY, ++ pk_backend_get_updates_thread); ++} ++ ++static gboolean ++pk_backend_refresh_cache_thread (PkBackend *self) ++{ ++ gint force; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (self != NULL, FALSE); ++ ++ /* download databases even if they are older than current */ ++ force = (gint) pk_backend_get_bool (self, "force"); ++ ++ pk_backend_update_databases (self, force, &error); ++ return pk_backend_finish (self, error); ++} ++ ++void ++pk_backend_refresh_cache (PkBackend *self, gboolean force) ++{ ++ g_return_if_fail (self != NULL); ++ ++ pk_backend_run (self, PK_STATUS_ENUM_SETUP, ++ pk_backend_refresh_cache_thread); ++} +diff --git a/backends/alpm/pk-backend-update.h b/backends/alpm/pk-backend-update.h +new file mode 100644 +index 0000000..368965a +--- /dev/null ++++ b/backends/alpm/pk-backend-update.h +@@ -0,0 +1,22 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007 Andreas Obergrusberger ++ * Copyright (C) 2008-2010 Valeriy Lyasotskiy ++ * Copyright (C) 2010-2011 Jonathan Conder ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ +diff --git a/backends/alpm/repos.list b/backends/alpm/repos.list +new file mode 100644 +index 0000000..191d31d +--- /dev/null ++++ b/backends/alpm/repos.list +@@ -0,0 +1 @@ ++# Generated by PackageKit +diff --git a/backends/pacman/Makefile.am b/backends/pacman/Makefile.am +deleted file mode 100644 +index 9ea0217..0000000 +--- a/backends/pacman/Makefile.am ++++ /dev/null +@@ -1,53 +0,0 @@ +-INCLUDES = \ +- -DG_LOG_DOMAIN=\"PackageKit-Pacman\" +- +-PACMAN_CONFIG_FILE = $(confdir)/pacman.conf +-PACMAN_GROUP_LIST = $(confdir)/groups.list +-PACMAN_REPO_LIST = $(confdir)/repos.list +-PACMAN_REPO_LIST_HEADER = "\# Generated by $(PACKAGE_NAME) - DO NOT MODIFY" +-PACMAN_CACHE_PATH = $(localstatedir)/lib/pacman/sync +-PACMAN_PACKAGE_URL = "http://www.archlinux.org/packages/%s/%s/%s/" +-PACMAN_DEFAULT_PATH = "/bin:/usr/bin:/sbin:/usr/sbin" +- +-DEFS = -DPACMAN_CONFIG_FILE=\"$(PACMAN_CONFIG_FILE)\" \ +- -DPACMAN_GROUP_LIST=\"$(PACMAN_GROUP_LIST)\" \ +- -DPACMAN_REPO_LIST=\"$(PACMAN_REPO_LIST)\" \ +- -DPACMAN_REPO_LIST_HEADER=\"$(PACMAN_REPO_LIST_HEADER)\" \ +- -DPACMAN_CACHE_PATH=\"$(PACMAN_CACHE_PATH)\" \ +- -DPACMAN_PACKAGE_URL=\"$(PACMAN_PACKAGE_URL)\" \ +- -DPACMAN_DEFAULT_PATH=\"$(PACMAN_DEFAULT_PATH)\" +- +-confdir = $(PK_CONF_DIR)/pacman.d +-conf_DATA = groups.list \ +- pacman.conf \ +- repos.list +- +-plugindir = $(PK_PLUGIN_DIR) +-plugin_LTLIBRARIES = libpk_backend_pacman.la +- +-libpk_backend_pacman_la_SOURCES = backend-depends.c \ +- backend-error.c \ +- backend-groups.c \ +- backend-install.c \ +- backend-packages.c \ +- backend-pacman.c \ +- backend-remove.c \ +- backend-repos.c \ +- backend-search.c \ +- backend-transaction.c \ +- backend-update.c +-libpk_backend_pacman_la_LIBADD = $(PK_PLUGIN_LIBS) \ +- $(PACMAN_LIBS) +-libpk_backend_pacman_la_LDFLAGS = -module -avoid-version +-libpk_backend_pacman_la_CFLAGS = $(PK_PLUGIN_CFLAGS) \ +- $(PACMAN_CFLAGS) \ +- $(WARNINGFLAGS_C) +- +-repos.list: +- echo $(PACMAN_REPO_LIST_HEADER) > $@ +- +-BUILT_SOURCES = repos.list +- +-EXTRA_DIST = $(conf_DATA) $(libpk_backend_pacman_la_SOURCES:.c=.h) +- +-CLEANFILES = $(BUILT_SOURCES) +diff --git a/backends/pacman/backend-depends.c b/backends/pacman/backend-depends.c +deleted file mode 100644 +index 9bd2324..0000000 +--- a/backends/pacman/backend-depends.c ++++ /dev/null +@@ -1,298 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include "backend-packages.h" +-#include "backend-pacman.h" +-#include "backend-repos.h" +-#include "backend-depends.h" +- +-static PacmanPackage * +-pacman_list_find_provider (const PacmanList *packages, PacmanDependency *depend) +-{ +- const PacmanList *list; +- +- g_return_val_if_fail (depend != NULL, NULL); +- +- /* find a package that provides depend */ +- for (list = packages; list != NULL; list = pacman_list_next (list)) { +- PacmanPackage *provider = (PacmanPackage *) pacman_list_get (list); +- +- if (pacman_dependency_satisfied_by (depend, provider)) { +- return provider; +- } +- } +- +- return NULL; +-} +- +-static PacmanPackage * +-pacman_sync_databases_find_provider (PacmanDependency *depend) +-{ +- const PacmanList *databases; +- +- g_return_val_if_fail (pacman != NULL, NULL); +- g_return_val_if_fail (depend != NULL, NULL); +- +- /* find the default package that provides depend */ +- for (databases = pacman_manager_get_sync_databases (pacman); databases != NULL; databases = pacman_list_next (databases)) { +- PacmanDatabase *database = (PacmanDatabase *) pacman_list_get (databases); +- PacmanPackage *provider = pacman_database_find_package (database, pacman_dependency_get_name (depend)); +- +- if (provider != NULL && pacman_dependency_satisfied_by (depend, provider)) { +- return provider; +- } +- } +- +- /* find any package that provides depend */ +- for (databases = pacman_manager_get_sync_databases (pacman); databases != NULL; databases = pacman_list_next (databases)) { +- PacmanDatabase *database = (PacmanDatabase *) pacman_list_get (databases); +- PacmanPackage *provider = pacman_list_find_provider (pacman_database_get_packages (database), depend); +- +- if (provider != NULL) { +- return provider; +- } +- } +- +- return NULL; +-} +- +-static gboolean +-backend_get_depends_thread (PkBackend *backend) +-{ +- guint iterator; +- PacmanList *list, *packages = NULL; +- +- PkBitfield filters; +- gchar **package_ids; +- gboolean recursive; +- +- gboolean search_installed; +- gboolean search_not_installed; +- +- g_return_val_if_fail (local_database != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- package_ids = pk_backend_get_strv (backend, "package_ids"); +- recursive = pk_backend_get_bool (backend, "recursive"); +- +- g_return_val_if_fail (package_ids != NULL, FALSE); +- +- filters = pk_backend_get_uint (backend, "filters"); +- search_installed = pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED); +- search_not_installed = pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED); +- +- /* construct an initial package list */ +- for (iterator = 0; package_ids[iterator] != NULL; ++iterator) { +- PacmanPackage *package = backend_get_package (backend, package_ids[iterator]); +- +- if (backend_cancelled (backend)) { +- break; +- } else if (package == NULL) { +- pacman_list_free (packages); +- backend_finished (backend); +- return FALSE; +- } +- +- packages = pacman_list_add (packages, package); +- } +- +- /* package list might be modified along the way but that is ok */ +- for (list = packages; list != NULL; list = pacman_list_next (list)) { +- PacmanPackage *package = (PacmanPackage *) pacman_list_get (list); +- const PacmanList *depends; +- +- if (backend_cancelled (backend)) { +- break; +- } +- +- for (depends = pacman_package_get_dependencies (package); depends != NULL; depends = pacman_list_next (depends)) { +- PacmanDependency *depend = (PacmanDependency *) pacman_list_get (depends); +- PacmanPackage *provider = pacman_list_find_provider (packages, depend); +- +- if (backend_cancelled (backend)) { +- break; +- } else if (provider != NULL) { +- continue; +- } +- +- /* look for installed dependencies */ +- provider = pacman_list_find_provider (pacman_database_get_packages (local_database), depend); +- if (provider != NULL) { +- /* don't emit when not needed... */ +- if (!search_not_installed) { +- backend_package (backend, provider, PK_INFO_ENUM_INSTALLED); +- /* ... and assume installed packages also have installed dependencies */ +- if (recursive) { +- packages = pacman_list_add (packages, provider); +- } +- } +- continue; +- } +- +- /* look for non-installed dependencies */ +- provider = pacman_sync_databases_find_provider (depend); +- if (provider != NULL) { +- /* don't emit when not needed... */ +- if (!search_installed) { +- backend_package (backend, provider, PK_INFO_ENUM_AVAILABLE); +- } +- /* ... but keep looking for installed dependencies */ +- if (recursive) { +- packages = pacman_list_add (packages, provider); +- } +- } else { +- gchar *depend_id = pacman_dependency_to_string (depend); +- pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, "Could not resolve dependency %s", depend_id); +- g_free (depend_id); +- +- pacman_list_free (packages); +- backend_finished (backend); +- return FALSE; +- } +- } +- } +- +- pacman_list_free (packages); +- backend_finished (backend); +- return TRUE; +-} +- +-/** +- * backend_get_depends: +- **/ +-void +-backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids, gboolean recursive) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package_ids != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_get_depends_thread); +-} +- +-static PacmanPackage * +-pacman_list_find_package (const PacmanList *packages, const gchar *name) +-{ +- const PacmanList *list; +- +- g_return_val_if_fail (name != NULL, NULL); +- +- /* find a package called name */ +- for (list = packages; list != NULL; list = pacman_list_next (list)) { +- PacmanPackage *package = (PacmanPackage *) pacman_list_get (list); +- +- if (g_strcmp0 (name, pacman_package_get_name (package)) == 0) { +- return package; +- } +- } +- +- return NULL; +-} +- +-static gboolean +-backend_get_requires_thread (PkBackend *backend) +-{ +- guint iterator; +- PacmanList *list, *packages = NULL; +- +- gchar **package_ids; +- gboolean recursive; +- +- g_return_val_if_fail (local_database != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- package_ids = pk_backend_get_strv (backend, "package_ids"); +- recursive = pk_backend_get_bool (backend, "recursive"); +- +- g_return_val_if_fail (package_ids != NULL, FALSE); +- +- /* construct an initial package list */ +- for (iterator = 0; package_ids[iterator] != NULL; ++iterator) { +- PacmanPackage *package = backend_get_package (backend, package_ids[iterator]); +- +- if (backend_cancelled (backend)) { +- break; +- } else if (package == NULL) { +- pacman_list_free (packages); +- backend_finished (backend); +- return FALSE; +- } +- +- packages = pacman_list_add (packages, package); +- } +- +- /* package list might be modified along the way but that is ok */ +- for (list = packages; list != NULL; list = pacman_list_next (list)) { +- PacmanPackage *package = (PacmanPackage *) pacman_list_get (list); +- PacmanList *requires, *required_by = pacman_package_find_required_by (package); +- +- if (backend_cancelled (backend)) { +- break; +- } +- +- for (requires = required_by; requires != NULL; requires = pacman_list_next (requires)) { +- const gchar *name = (const gchar *) pacman_list_get (requires); +- PacmanPackage *requirer = pacman_list_find_package (packages, name); +- +- if (backend_cancelled (backend)) { +- break; +- } else if (requirer != NULL) { +- continue; +- } +- +- /* look for installed requirers */ +- requirer = pacman_database_find_package (local_database, name); +- if (requirer == NULL) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, "Could not find package %s", name); +- +- pacman_list_free_full (required_by, g_free); +- pacman_list_free (packages); +- backend_finished (backend); +- return FALSE; +- } +- +- backend_package (backend, requirer, PK_INFO_ENUM_INSTALLED); +- if (recursive) { +- packages = pacman_list_add (packages, requirer); +- } +- } +- +- pacman_list_free_full (required_by, g_free); +- } +- +- pacman_list_free (packages); +- backend_finished (backend); +- return TRUE; +-} +- +-/** +- * backend_get_requires: +- **/ +-void +-backend_get_requires (PkBackend *backend, PkBitfield filters, gchar **package_ids, gboolean recursive) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package_ids != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_get_requires_thread); +-} +diff --git a/backends/pacman/backend-depends.h b/backends/pacman/backend-depends.h +deleted file mode 100644 +index c6f7b6a..0000000 +--- a/backends/pacman/backend-depends.h ++++ /dev/null +@@ -1,33 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +- +-void backend_get_depends (PkBackend *backend, +- PkBitfield filters, +- gchar **package_ids, +- gboolean recursive); +-void backend_get_requires (PkBackend *backend, +- PkBitfield filters, +- gchar **package_ids, +- gboolean recursive); +diff --git a/backends/pacman/backend-error.c b/backends/pacman/backend-error.c +deleted file mode 100644 +index 2336508..0000000 +--- a/backends/pacman/backend-error.c ++++ /dev/null +@@ -1,185 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include "backend-error.h" +- +-void +-backend_error (PkBackend *backend, GError *error) +-{ +- PkErrorEnum code = PK_ERROR_ENUM_INTERNAL_ERROR; +- +- g_return_if_fail (backend != NULL); +- g_return_if_fail (error != NULL); +- +- /* convert error codes */ +- if (error->domain == PACMAN_ERROR) { +- switch (error->code) { +- case PACMAN_ERROR_MEMORY: +- code = PK_ERROR_ENUM_OOM; +- break; +- +- case PACMAN_ERROR_SYSTEM: +- case PACMAN_ERROR_INVALID_ARGS: +- case PACMAN_ERROR_NOT_INITIALIZED: +- case PACMAN_ERROR_DATABASE_NOT_INITIALIZED: +- case PACMAN_ERROR_SERVER_INVALID_URL: +- case PACMAN_ERROR_REGEX_INVALID: +- case PACMAN_ERROR_LIBARCHIVE: +- case PACMAN_ERROR_LIBFETCH: +- case PACMAN_ERROR_DOWNLOAD_HANDLER: +- code = PK_ERROR_ENUM_INTERNAL_ERROR; +- break; +- +- case PACMAN_ERROR_NOT_PERMITTED: +- code = PK_ERROR_ENUM_NOT_AUTHORIZED; +- break; +- +- case PACMAN_ERROR_FILE_NOT_FOUND: +- case PACMAN_ERROR_DIRECTORY_NOT_FOUND: +- code = PK_ERROR_ENUM_FILE_NOT_FOUND; +- break; +- +- case PACMAN_ERROR_ALREADY_INITIALIZED: +- case PACMAN_ERROR_DATABASE_ALREADY_INITIALIZED: +- code = PK_ERROR_ENUM_FAILED_INITIALIZATION; +- break; +- +- case PACMAN_ERROR_ALREADY_RUNNING: +- code = PK_ERROR_ENUM_CANNOT_GET_LOCK; +- break; +- +- case PACMAN_ERROR_DATABASE_OPEN_FAILED: +- code = PK_ERROR_ENUM_REPO_NOT_FOUND; +- break; +- +- case PACMAN_ERROR_DATABASE_CREATE_FAILED: +- code = PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG; +- break; +- +- case PACMAN_ERROR_DATABASE_NOT_FOUND: +- code = PK_ERROR_ENUM_REPO_NOT_FOUND; +- break; +- +- case PACMAN_ERROR_DATABASE_UPDATE_FAILED: +- code = PK_ERROR_ENUM_REPO_NOT_AVAILABLE; +- break; +- +- case PACMAN_ERROR_DATABASE_REMOVE_FAILED: +- code = PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR; +- break; +- +- case PACMAN_ERROR_SERVER_NONE_AVAILABLE: +- code = PK_ERROR_ENUM_NO_MORE_MIRRORS_TO_TRY; +- break; +- +- case PACMAN_ERROR_TRANSACTION_ALREADY_INITIALIZED: +- case PACMAN_ERROR_TRANSACTION_NOT_INITIALIZED: +- case PACMAN_ERROR_TRANSACTION_DUPLICATE_TARGET: +- case PACMAN_ERROR_TRANSACTION_NOT_READY: +- case PACMAN_ERROR_TRANSACTION_NOT_PREPARED: +- case PACMAN_ERROR_TRANSACTION_INVALID_OPERATION: +- case PACMAN_ERROR_TRANSACTION_NOT_LOCKED: +- code = PK_ERROR_ENUM_TRANSACTION_ERROR; +- break; +- +- case PACMAN_ERROR_TRANSACTION_ABORTED: +- code = PK_ERROR_ENUM_TRANSACTION_CANCELLED; +- break; +- +- case PACMAN_ERROR_PACKAGE_NOT_FOUND: +- code = PK_ERROR_ENUM_PACKAGE_NOT_FOUND; +- break; +- +- case PACMAN_ERROR_PACKAGE_IGNORED: +- code = PK_ERROR_ENUM_PACKAGE_INSTALL_BLOCKED; +- break; +- +- case PACMAN_ERROR_DELTA_INVALID: +- case PACMAN_ERROR_PACKAGE_INVALID: +- code = PK_ERROR_ENUM_INVALID_PACKAGE_FILE; +- break; +- +- case PACMAN_ERROR_PACKAGE_OPEN_FAILED: +- code = PK_ERROR_ENUM_PACKAGE_NOT_FOUND; +- break; +- +- case PACMAN_ERROR_PACKAGE_REMOVE_FAILED: +- code = PK_ERROR_ENUM_PACKAGE_FAILED_TO_REMOVE; +- break; +- +- case PACMAN_ERROR_PACKAGE_UNKNOWN_FILENAME: +- case PACMAN_ERROR_PACKAGE_DATABASE_NOT_FOUND: +- code = PK_ERROR_ENUM_PACKAGE_FAILED_TO_CONFIGURE; +- break; +- +- case PACMAN_ERROR_DELTA_PATCH_FAILED: +- code = PK_ERROR_ENUM_PACKAGE_FAILED_TO_BUILD; +- break; +- +- case PACMAN_ERROR_DEPENDENCY_UNSATISFIED: +- code = PK_ERROR_ENUM_DEP_RESOLUTION_FAILED; +- break; +- +- case PACMAN_ERROR_CONFLICT: +- code = PK_ERROR_ENUM_PACKAGE_CONFLICTS; +- break; +- +- case PACMAN_ERROR_FILE_CONFLICT: +- code = PK_ERROR_ENUM_FILE_CONFLICTS; +- break; +- +- case PACMAN_ERROR_DOWNLOAD_FAILED: +- code = PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED; +- break; +- +- case PACMAN_ERROR_CONFIG_INVALID: +- code = PK_ERROR_ENUM_FAILED_CONFIG_PARSING; +- break; +- +- case PACMAN_ERROR_PACKAGE_HELD: +- code = PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE; +- break; +- } +- } +- +- pk_backend_error_code (backend, code, "%s", error->message); +- g_error_free (error); +-} +- +-void +-backend_message (PkBackend *backend, const gchar *message) +-{ +- guint iterator; +- gchar **messages = g_strsplit_set (message, "\r\n", 0); +- +- /* display multi-line messages in a nice format */ +- for (iterator = 0; messages[iterator] != NULL; ++iterator) { +- g_strstrip (messages[iterator]); +- if (*messages[iterator] != '\0') { +- pk_backend_message (backend, PK_MESSAGE_ENUM_UNKNOWN, "%s", messages[iterator]); +- } +- } +- +- g_strfreev (messages); +-} +diff --git a/backends/pacman/backend-error.h b/backends/pacman/backend-error.h +deleted file mode 100644 +index 2be8021..0000000 +--- a/backends/pacman/backend-error.h ++++ /dev/null +@@ -1,29 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +- +-void backend_error (PkBackend *backend, +- GError *error); +-void backend_message (PkBackend *backend, +- const gchar *message); +diff --git a/backends/pacman/backend-groups.c b/backends/pacman/backend-groups.c +deleted file mode 100644 +index 95ebce6..0000000 +--- a/backends/pacman/backend-groups.c ++++ /dev/null +@@ -1,150 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include +-#include "backend-error.h" +-#include "backend-groups.h" +- +-static GHashTable *group_map = NULL; +-static PkBitfield groups = 0; +- +-static GHashTable * +-group_map_new (GError **error) +-{ +- GHashTable *map; +- GFile *file; +- +- GFileInputStream *file_stream; +- GDataInputStream *data_stream; +- +- gchar *key, *value; +- GError *e = NULL; +- +- g_debug ("pacman: reading groups from %s", PACMAN_GROUP_LIST); +- file = g_file_new_for_path (PACMAN_GROUP_LIST); +- file_stream = g_file_read (file, NULL, &e); +- +- if (file_stream == NULL) { +- g_object_unref (file); +- g_propagate_error (error, e); +- return NULL; +- } +- +- map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); +- data_stream = g_data_input_stream_new (G_INPUT_STREAM (file_stream)); +- +- /* read groups line by line, ignoring comments */ +- while ((value = g_data_input_stream_read_line (data_stream, NULL, NULL, &e)) != NULL) { +- PkGroupEnum group; +- +- g_strstrip (value); +- if (*value == '\0' || *value == '#') { +- g_free (value); +- continue; +- } +- +- /* line format: alpm-group (space|tab)+ packagekit-group */ +- key = strsep (&value, " "); +- g_strchomp (key); +- +- if (value == NULL) { +- /* safe to cast as it is never freed or modified */ +- value = (gchar *) "other"; +- group = PK_GROUP_ENUM_OTHER; +- } else { +- g_strchug (value); +- group = pk_group_enum_from_string (value); +- } +- +- if (group != PK_GROUP_ENUM_UNKNOWN) { +- /* use replace because key and value are allocated together */ +- g_hash_table_replace (map, key, value); +- pk_bitfield_add (groups, group); +- } +- } +- +- g_object_unref (data_stream); +- g_object_unref (file_stream); +- g_object_unref (file); +- +- if (e != NULL) { +- g_hash_table_unref (map); +- g_propagate_error (error, e); +- return NULL; +- } else { +- return map; +- } +-} +- +-gboolean +-backend_initialize_groups (PkBackend *backend, GError **error) +-{ +- g_return_val_if_fail (backend != NULL, FALSE); +- +- group_map = group_map_new (error); +- if (group_map == NULL) { +- return FALSE; +- } +- +- return TRUE; +-} +- +-void +-backend_destroy_groups (PkBackend *backend) +-{ +- g_return_if_fail (backend != NULL); +- +- if (group_map != NULL) { +- g_hash_table_unref (group_map); +- } +-} +- +-const gchar * +-pacman_package_get_group (PacmanPackage *package) +-{ +- const PacmanList *list; +- +- g_return_val_if_fail (group_map != NULL, NULL); +- g_return_val_if_fail (package != NULL, NULL); +- +- /* use the first group that we recognise */ +- for (list = pacman_package_get_groups (package); list != NULL; list = pacman_list_next (list)) { +- gpointer value = g_hash_table_lookup (group_map, pacman_list_get (list)); +- if (value != NULL) { +- return (const gchar *) value; +- } +- } +- +- return "other"; +-} +- +-/** +- * backend_get_groups: +- **/ +-PkBitfield backend_get_groups (PkBackend *backend) +-{ +- g_return_val_if_fail (backend != NULL, 0); +- +- return groups; +-} +diff --git a/backends/pacman/backend-groups.h b/backends/pacman/backend-groups.h +deleted file mode 100644 +index 9642015..0000000 +--- a/backends/pacman/backend-groups.h ++++ /dev/null +@@ -1,32 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include +- +-gboolean backend_initialize_groups (PkBackend *backend, +- GError **error); +-void backend_destroy_groups (PkBackend *backend); +- +-const gchar *pacman_package_get_group (PacmanPackage *package); +-PkBitfield backend_get_groups (PkBackend *backend); +diff --git a/backends/pacman/backend-install.c b/backends/pacman/backend-install.c +deleted file mode 100644 +index 5c188cc..0000000 +--- a/backends/pacman/backend-install.c ++++ /dev/null +@@ -1,348 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include "backend-error.h" +-#include "backend-pacman.h" +-#include "backend-packages.h" +-#include "backend-repos.h" +-#include "backend-transaction.h" +-#include "backend-install.h" +- +-static PacmanList * +-backend_transaction_list_targets (PkBackend *backend) +-{ +- gchar **package_ids; +- guint iterator; +- PacmanList *list = NULL; +- +- g_return_val_if_fail (backend != NULL, NULL); +- +- package_ids = pk_backend_get_strv (backend, "package_ids"); +- +- g_return_val_if_fail (package_ids != NULL, NULL); +- +- for (iterator = 0; package_ids[iterator] != NULL; ++iterator) { +- gchar **package_id_data = pk_package_id_split (package_ids[iterator]); +- list = pacman_list_add (list, g_strdup_printf ("%s/%s", package_id_data[PK_PACKAGE_ID_DATA], package_id_data[PK_PACKAGE_ID_NAME])); +- g_strfreev (package_id_data); +- } +- +- return list; +-} +- +-static gboolean +-backend_download_packages_thread (PkBackend *backend) +-{ +- PacmanList *list; +- PacmanList *cache_paths; +- const gchar *directory; +- +- PacmanTransaction *transaction = NULL; +- PacmanTransactionFlags flags = PACMAN_TRANSACTION_FLAGS_IGNORE_DEPENDENCIES | +- PACMAN_TRANSACTION_FLAGS_IGNORE_DEPENDENCY_CONFLICTS | +- PACMAN_TRANSACTION_FLAGS_SYNC_DOWNLOAD_ONLY; +- +- g_return_val_if_fail (pacman != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- directory = pk_backend_get_string (backend, "directory"); +- +- g_return_val_if_fail (directory != NULL, FALSE); +- +- /* download files to a PackageKit directory */ +- cache_paths = pacman_list_strdup (pacman_manager_get_cache_paths (pacman)); +- pacman_manager_set_cache_paths (pacman, NULL); +- pacman_manager_add_cache_path (pacman, directory); +- +- /* run the transaction */ +- list = backend_transaction_list_targets (backend); +- if (list != NULL) { +- transaction = backend_transaction_run (backend, PACMAN_TRANSACTION_SYNC, flags, list); +- pacman_list_free_full (list, g_free); +- } +- +- pacman_manager_set_cache_paths (pacman, cache_paths); +- pacman_list_free_full (cache_paths, g_free); +- return backend_transaction_finished (backend, transaction); +-} +- +-/** +- * backend_download_packages: +- **/ +-void +-backend_download_packages (PkBackend *backend, gchar **package_ids, const gchar *directory) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package_ids != NULL); +- g_return_if_fail (directory != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_SETUP, backend_download_packages_thread); +-} +- +-static gboolean +-backend_install_files_thread (PkBackend *backend) +-{ +- guint iterator; +- PacmanList *list = NULL; +- +- /* FS#5331: use only_trusted */ +- gchar **full_paths; +- +- PacmanTransaction *transaction = NULL; +- PacmanTransactionFlags flags = PACMAN_TRANSACTION_FLAGS_NONE; +- +- g_return_val_if_fail (backend != NULL, FALSE); +- +- full_paths = pk_backend_get_strv (backend, "full_paths"); +- +- g_return_val_if_fail (full_paths != NULL, FALSE); +- +- /* run the transaction */ +- for (iterator = 0; full_paths[iterator] != NULL; ++iterator) { +- list = pacman_list_add (list, full_paths[iterator]); +- } +- if (list != NULL) { +- transaction = backend_transaction_run (backend, PACMAN_TRANSACTION_INSTALL, flags, list); +- pacman_list_free (list); +- } +- +- return backend_transaction_finished (backend, transaction); +-} +- +-/** +- * backend_install_files: +- **/ +-void +-backend_install_files (PkBackend *backend, gboolean only_trusted, gchar **full_paths) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (full_paths != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_SETUP, backend_install_files_thread); +-} +- +-static gboolean +-backend_simulate_install_files_thread (PkBackend *backend) +-{ +- guint iterator; +- PacmanList *list = NULL; +- +- gchar **full_paths; +- +- PacmanTransaction *transaction = NULL; +- PacmanTransactionFlags flags = PACMAN_TRANSACTION_FLAGS_NONE; +- +- g_return_val_if_fail (backend != NULL, FALSE); +- +- full_paths = pk_backend_get_strv (backend, "full_paths"); +- +- g_return_val_if_fail (full_paths != NULL, FALSE); +- +- /* prepare the transaction */ +- for (iterator = 0; full_paths[iterator] != NULL; ++iterator) { +- list = pacman_list_add (list, full_paths[iterator]); +- } +- if (list != NULL) { +- transaction = backend_transaction_simulate (backend, PACMAN_TRANSACTION_INSTALL, flags, list); +- pacman_list_free (list); +- +- if (transaction != NULL) { +- /* emit packages that would have been installed or removed */ +- backend_transaction_packages (backend, transaction); +- } +- } +- +- return backend_transaction_finished (backend, transaction); +-} +- +-/** +- * backend_install_files: +- **/ +-void +-backend_simulate_install_files (PkBackend *backend, gchar **full_paths) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (full_paths != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_SETUP, backend_simulate_install_files_thread); +-} +- +-static gboolean +-backend_install_packages_thread (PkBackend *backend) +-{ +- PacmanList *list; +- /* FS#5331: use only_trusted */ +- PacmanTransaction *transaction = NULL; +- PacmanTransactionFlags flags = PACMAN_TRANSACTION_FLAGS_NONE; +- +- g_return_val_if_fail (backend != NULL, FALSE); +- +- /* run the transaction */ +- list = backend_transaction_list_targets (backend); +- if (list != NULL) { +- transaction = backend_transaction_run (backend, PACMAN_TRANSACTION_SYNC, flags, list); +- pacman_list_free_full (list, g_free); +- } +- +- return backend_transaction_finished (backend, transaction); +-} +- +-/** +- * backend_install_packages: +- **/ +-void +-backend_install_packages (PkBackend *backend, gboolean only_trusted, gchar **package_ids) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package_ids != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_SETUP, backend_install_packages_thread); +-} +- +-static gboolean +-backend_simulate_install_packages_thread (PkBackend *backend) +-{ +- PacmanList *list; +- +- PacmanTransaction *transaction = NULL; +- PacmanTransactionFlags flags = PACMAN_TRANSACTION_FLAGS_NONE; +- +- g_return_val_if_fail (backend != NULL, FALSE); +- +- /* prepare the transaction */ +- list = backend_transaction_list_targets (backend); +- if (list != NULL) { +- transaction = backend_transaction_simulate (backend, PACMAN_TRANSACTION_SYNC, flags, list); +- pacman_list_free_full (list, g_free); +- +- if (transaction != NULL) { +- /* emit packages that would have been installed or removed */ +- backend_transaction_packages (backend, transaction); +- } +- } +- +- return backend_transaction_finished (backend, transaction); +-} +- +-/** +- * backend_simulate_install_packages: +- **/ +-void +-backend_simulate_install_packages (PkBackend *backend, gchar **package_ids) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package_ids != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_SETUP, backend_simulate_install_packages_thread); +-} +- +-static gboolean +-backend_update_packages_thread (PkBackend *backend) +-{ +- PacmanList *list, *asdeps = NULL; +- /* FS#5331: use only_trusted */ +- PacmanTransaction *transaction = NULL; +- PacmanTransactionFlags sflags = PACMAN_TRANSACTION_FLAGS_NONE, mflags = PACMAN_TRANSACTION_FLAGS_INSTALL_IMPLICIT; +- +- g_return_val_if_fail (local_database != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- /* prepare the transaction */ +- list = backend_transaction_list_targets (backend); +- if (list != NULL) { +- transaction = backend_transaction_simulate (backend, PACMAN_TRANSACTION_SYNC, sflags, list); +- pacman_list_free_full (list, g_free); +- +- if (transaction != NULL) { +- const PacmanList *installs, *removes; +- +- /* change the install reason of for packages that replace only dependencies of other packages */ +- for (installs = pacman_transaction_get_installs (transaction); installs != NULL; installs = pacman_list_next (installs)) { +- PacmanPackage *install = (PacmanPackage *) pacman_list_get (installs); +- const gchar *name = pacman_package_get_name (install); +- +- if (backend_cancelled (backend)) { +- break; +- } else if (pacman_database_find_package (local_database, name) == NULL) { +- const PacmanList *replaces = pacman_package_get_replaces (install); +- +- for (removes = pacman_transaction_get_removes (transaction); removes != NULL; removes = pacman_list_next (removes)) { +- PacmanPackage *remove = (PacmanPackage *) pacman_list_get (removes); +- const gchar *replace = pacman_package_get_name (remove); +- +- if (backend_cancelled (backend)) { +- break; +- } else if (pacman_list_find_string (replaces, replace)) { +- if (pacman_package_was_explicitly_installed (remove)) { +- break; +- } +- } +- } +- +- /* none of the replaced packages were installed explicitly */ +- if (removes == NULL) { +- asdeps = pacman_list_add (asdeps, g_strdup (name)); +- } +- } +- } +- +- transaction = backend_transaction_commit (backend, transaction); +- } +- } +- +- /* mark replacements as deps if required */ +- if (asdeps != NULL) { +- if (transaction != NULL) { +- g_object_unref (transaction); +- transaction = backend_transaction_run (backend, PACMAN_TRANSACTION_MODIFY, mflags, asdeps); +- } +- pacman_list_free_full (asdeps, g_free); +- } +- +- return backend_transaction_finished (backend, transaction); +-} +- +-/** +- * backend_update_packages: +- **/ +-void +-backend_update_packages (PkBackend *backend, gboolean only_trusted, gchar **package_ids) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package_ids != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_SETUP, backend_update_packages_thread); +-} +- +-/** +- * backend_simulate_update_packages: +- **/ +-void +-backend_simulate_update_packages (PkBackend *backend, gchar **package_ids) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package_ids != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_SETUP, backend_simulate_install_packages_thread); +-} +diff --git a/backends/pacman/backend-install.h b/backends/pacman/backend-install.h +deleted file mode 100644 +index 0685a48..0000000 +--- a/backends/pacman/backend-install.h ++++ /dev/null +@@ -1,45 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +- +-void backend_download_packages (PkBackend *backend, +- gchar **package_ids, +- const gchar *directory); +-void backend_install_files (PkBackend *backend, +- gboolean only_trusted, +- gchar **full_paths); +-void backend_simulate_install_files (PkBackend *backend, +- gchar **full_paths); +- +-void backend_install_packages (PkBackend *backend, +- gboolean only_trusted, +- gchar **package_ids); +-void backend_simulate_install_packages (PkBackend *backend, +- gchar **package_ids); +- +-void backend_update_packages (PkBackend *backend, +- gboolean only_trusted, +- gchar **package_ids); +-void backend_simulate_update_packages (PkBackend *backend, +- gchar **package_ids); +diff --git a/backends/pacman/backend-packages.c b/backends/pacman/backend-packages.c +deleted file mode 100644 +index a00f107..0000000 +--- a/backends/pacman/backend-packages.c ++++ /dev/null +@@ -1,345 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include "backend-groups.h" +-#include "backend-pacman.h" +-#include "backend-repos.h" +-#include "backend-packages.h" +- +-gchar * +-pacman_package_make_id (PacmanPackage *package) +-{ +- const gchar *name, *version, *arch, *repo; +- PacmanDatabase *database; +- +- g_return_val_if_fail (local_database != NULL, NULL); +- g_return_val_if_fail (package != NULL, NULL); +- +- name = pacman_package_get_name (package); +- version = pacman_package_get_version (package); +- +- arch = pacman_package_get_arch (package); +- if (arch == NULL) { +- arch = "any"; +- } +- +- /* PackageKit requires "local" for package files and "installed" for installed packages */ +- database = pacman_package_get_database (package); +- if (database == NULL) { +- repo = "local"; +- } else if (database == local_database) { +- repo = "installed"; +- } else { +- repo = pacman_database_get_name (database); +- } +- +- return pk_package_id_build (name, version, arch, repo); +-} +- +-void +-backend_package (PkBackend *backend, PacmanPackage *package, PkInfoEnum info) +-{ +- gchar *package_id; +- +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package != NULL); +- +- /* build and emit package id */ +- package_id = pacman_package_make_id (package); +- pk_backend_package (backend, info, package_id, pacman_package_get_description (package)); +- g_free (package_id); +-} +- +-PacmanPackage * +-backend_get_package (PkBackend *backend, const gchar *package_id) +-{ +- gchar **package_id_data; +- const gchar *repo; +- PacmanDatabase *database; +- PacmanPackage *package; +- +- g_return_val_if_fail (pacman != NULL, NULL); +- g_return_val_if_fail (local_database != NULL, NULL); +- g_return_val_if_fail (backend != NULL, NULL); +- g_return_val_if_fail (package_id != NULL, NULL); +- +- package_id_data = pk_package_id_split (package_id); +- repo = package_id_data[PK_PACKAGE_ID_DATA]; +- +- /* find the database to search in */ +- if (g_strcmp0 (repo, "installed") == 0) { +- database = local_database; +- } else { +- database = pacman_manager_find_sync_database (pacman, repo); +- } +- +- if (database == NULL) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, "Could not find repo [%s]", repo); +- g_strfreev (package_id_data); +- return NULL; +- } +- +- /* find the package in the database */ +- package = pacman_database_find_package (database, package_id_data[PK_PACKAGE_ID_NAME]); +- if (package == NULL || g_strcmp0 (pacman_package_get_version (package), package_id_data[PK_PACKAGE_ID_VERSION]) != 0) { +- pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, "Could not find package with ID %s", package_id); +- g_strfreev (package_id_data); +- return NULL; +- } +- +- g_strfreev (package_id_data); +- return package; +-} +- +-static gboolean +-backend_resolve_thread (PkBackend *backend) +-{ +- guint iterator; +- +- gchar **package_ids; +- PkBitfield filters; +- +- gboolean search_installed; +- gboolean search_not_installed; +- +- g_return_val_if_fail (pacman != NULL, FALSE); +- g_return_val_if_fail (local_database != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- package_ids = pk_backend_get_strv (backend, "package_ids"); +- filters = pk_backend_get_uint (backend, "filters"); +- +- g_return_val_if_fail (package_ids != NULL, FALSE); +- +- search_installed = pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED); +- search_not_installed = pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED); +- +- for (iterator = 0; package_ids[iterator] != NULL; ++iterator) { +- if (backend_cancelled (backend)) { +- break; +- } +- +- /* find a package with the given id or name */ +- if (pk_package_id_check (package_ids[iterator])) { +- PacmanPackage *package = backend_get_package (backend, package_ids[iterator]); +- if (package == NULL) { +- backend_finished (backend); +- return FALSE; +- } +- +- /* don't emit when not needed */ +- if (pacman_package_get_database (package) == local_database) { +- if (!search_not_installed) { +- backend_package (backend, package, PK_INFO_ENUM_INSTALLED); +- } +- } else { +- if (!search_installed) { +- backend_package (backend, package, PK_INFO_ENUM_AVAILABLE); +- } +- } +- } else { +- /* find installed packages first */ +- if (!search_not_installed) { +- PacmanPackage *package = pacman_database_find_package (local_database, package_ids[iterator]); +- +- if (package != NULL) { +- backend_package (backend, package, PK_INFO_ENUM_INSTALLED); +- continue; +- } +- } +- +- if (!search_installed) { +- const PacmanList *databases; +- +- for (databases = pacman_manager_get_sync_databases (pacman); databases != NULL; databases = pacman_list_next (databases)) { +- PacmanDatabase *database = (PacmanDatabase *) pacman_list_get (databases); +- PacmanPackage *package = pacman_database_find_package (database, package_ids[iterator]); +- +- if (package != NULL) { +- backend_package (backend, package, PK_INFO_ENUM_AVAILABLE); +- break; +- } +- } +- } +- } +- } +- +- backend_finished (backend); +- return TRUE; +-} +- +-/** +- * backend_resolve: +- **/ +-void +-backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package_ids != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_resolve_thread); +-} +- +-static gboolean +-backend_get_details_thread (PkBackend *backend) +-{ +- guint iterator; +- +- gchar **package_ids; +- +- g_return_val_if_fail (local_database != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- package_ids = pk_backend_get_strv (backend, "package_ids"); +- +- g_return_val_if_fail (package_ids != NULL, FALSE); +- +- /* collect details about packages */ +- for (iterator = 0; package_ids[iterator] != NULL; ++iterator) { +- PacmanPackage *package; +- const PacmanList *list; +- GString *string; +- +- gchar *licenses; +- PkGroupEnum group; +- const gchar *description, *url; +- gulong size; +- +- if (backend_cancelled (backend)) { +- break; +- } +- +- package = backend_get_package (backend, package_ids[iterator]); +- if (package == NULL) { +- backend_finished (backend); +- return FALSE; +- } +- +- list = pacman_package_get_licenses (package); +- if (list == NULL) { +- string = g_string_new ("unknown"); +- } else { +- string = g_string_new ((const gchar *) pacman_list_get (list)); +- for (list = pacman_list_next (list); list != NULL; list = pacman_list_next (list)) { +- /* assume OR although it may not be correct */ +- g_string_append_printf (string, " or %s", (const gchar *) pacman_list_get (list)); +- } +- } +- +- group = pk_group_enum_from_string (pacman_package_get_group (package)); +- description = pacman_package_get_description (package); +- url = pacman_package_get_url (package); +- +- if (pacman_package_get_database (package) == local_database) { +- size = pacman_package_get_installed_size (package); +- } else { +- size = pacman_package_get_download_size (package); +- } +- +- licenses = g_string_free (string, FALSE); +- pk_backend_details (backend, package_ids[iterator], licenses, group, description, url, size); +- g_free (licenses); +- } +- +- backend_finished (backend); +- return TRUE; +-} +- +-/** +- * backend_get_details: +- **/ +-void +-backend_get_details (PkBackend *backend, gchar **package_ids) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package_ids != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_get_details_thread); +-} +- +-static gboolean +-backend_get_files_thread (PkBackend *backend) +-{ +- guint iterator; +- +- gchar **package_ids; +- +- g_return_val_if_fail (pacman != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- package_ids = pk_backend_get_strv (backend, "package_ids"); +- +- g_return_val_if_fail (package_ids != NULL, FALSE); +- +- /* enumerate files provided by package */ +- for (iterator = 0; package_ids[iterator] != NULL; ++iterator) { +- PacmanPackage *package; +- const PacmanList *list; +- +- GString *string; +- gchar *files; +- +- if (backend_cancelled (backend)) { +- break; +- } +- +- package = backend_get_package (backend, package_ids[iterator]); +- if (package == NULL) { +- backend_finished (backend); +- return FALSE; +- } +- +- list = pacman_package_get_files (package); +- if (list == NULL) { +- string = g_string_new (""); +- } else { +- const gchar *root_path = pacman_manager_get_root_path (pacman); +- string = g_string_new (root_path); +- g_string_append (string, (const gchar *) pacman_list_get (list)); +- +- for (list = pacman_list_next (list); list != NULL; list = pacman_list_next (list)) { +- g_string_append_printf (string, ";%s%s", root_path, (const gchar *) pacman_list_get (list)); +- } +- } +- +- files = g_string_free (string, FALSE); +- pk_backend_files (backend, package_ids[iterator], files); +- g_free (files); +- } +- +- backend_finished (backend); +- return TRUE; +-} +- +-/** +- * backend_get_files: +- **/ +-void +-backend_get_files (PkBackend *backend, gchar **package_ids) +-{ +- g_return_if_fail (pacman != NULL); +- g_return_if_fail (backend != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_get_files_thread); +-} +diff --git a/backends/pacman/backend-packages.h b/backends/pacman/backend-packages.h +deleted file mode 100644 +index 2064b89..0000000 +--- a/backends/pacman/backend-packages.h ++++ /dev/null +@@ -1,41 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include +- +-gchar *pacman_package_make_id (PacmanPackage *package); +-void backend_package (PkBackend *backend, +- PacmanPackage *package, +- PkInfoEnum info); +- +-PacmanPackage *backend_get_package (PkBackend *backend, +- const gchar *package_id); +-void backend_resolve (PkBackend *backend, +- PkBitfield filters, +- gchar **package_ids); +- +-void backend_get_details (PkBackend *backend, +- gchar **package_ids); +-void backend_get_files (PkBackend *backend, +- gchar **package_ids); +diff --git a/backends/pacman/backend-pacman.c b/backends/pacman/backend-pacman.c +deleted file mode 100644 +index 1276f15..0000000 +--- a/backends/pacman/backend-pacman.c ++++ /dev/null +@@ -1,260 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include "backend-depends.h" +-#include "backend-error.h" +-#include "backend-groups.h" +-#include "backend-install.h" +-#include "backend-packages.h" +-#include "backend-remove.h" +-#include "backend-repos.h" +-#include "backend-search.h" +-#include "backend-transaction.h" +-#include "backend-update.h" +-#include "backend-pacman.h" +- +-PacmanManager *pacman = NULL; +-GCancellable *cancellable = NULL; +- +-static void +-pacman_message_cb (const gchar *domain, GLogLevelFlags level, const gchar *message, gpointer user_data) +-{ +- g_return_if_fail (message != NULL); +- g_return_if_fail (user_data != NULL); +- +-/* disable due to recursive logging, will fix via improving alpm backend */ +-#if 0 +- /* report important output to PackageKit */ +- switch (level) { +- case G_LOG_LEVEL_WARNING: +- case G_LOG_LEVEL_MESSAGE: +- g_warning ("pacman: %s", message); +- backend_message ((PkBackend *) user_data, message); +- break; +- +- case G_LOG_LEVEL_INFO: +- case G_LOG_LEVEL_DEBUG: +- g_debug ("pacman: %s", message); +- break; +- +- default: +- g_warning ("pacman: %s", message); +- break; +- } +-#endif +-} +- +-/** +- * backend_initialize: +- **/ +-static void +-backend_initialize (PkBackend *backend) +-{ +- GError *error = NULL; +- GLogLevelFlags flags = G_LOG_LEVEL_MASK; +- +- g_return_if_fail (backend != NULL); +- +- /* handle output from pacman */ +- g_log_set_handler ("Pacman", flags, pacman_message_cb, backend); +- +- /* PATH needs to be set for install scriptlets */ +- g_setenv ("PATH", PACMAN_DEFAULT_PATH, FALSE); +- +- g_debug ("pacman: initializing"); +- +- /* initialize pacman-glib */ +- pacman = pacman_manager_get (&error); +- if (pacman == NULL) { +- g_error ("pacman: %s", error->message); +- g_error_free (error); +- return; +- } +- +- /* configure and disable the relevant databases */ +- if (!backend_initialize_databases (backend, &error)) { +- g_error ("pacman: %s", error->message); +- g_error_free (error); +- return; +- } +- +- /* read the group mapping from a config file */ +- if (!backend_initialize_groups (backend, &error)) { +- g_error ("pacman: %s", error->message); +- g_error_free (error); +- return; +- } +- +- /* setup better download progress reporting */ +- if (!backend_initialize_downloads (backend, &error)) { +- g_error ("pacman: %s", error->message); +- g_error_free (error); +- return; +- } +-} +- +-/** +- * backend_destroy: +- **/ +-static void +-backend_destroy (PkBackend *backend) +-{ +- g_return_if_fail (backend != NULL); +- +- g_debug ("pacman: cleaning up"); +- +- backend_destroy_downloads (backend); +- backend_destroy_groups (backend); +- backend_destroy_databases (backend); +- +- if (pacman != NULL) { +- g_object_unref (pacman); +- } +-} +- +-/** +- * backend_get_filters: +- **/ +-static PkBitfield +-backend_get_filters (PkBackend *backend) +-{ +- g_return_val_if_fail (backend != NULL, 0); +- +- return pk_bitfield_from_enums (PK_FILTER_ENUM_INSTALLED, -1); +-} +- +-/** +- * backend_get_mime_types: +- **/ +-static gchar * +-backend_get_mime_types (PkBackend *backend) +-{ +- g_return_val_if_fail (backend != NULL, NULL); +- +- /* packages currently use .pkg.tar.gz and .pkg.tar.xz */ +- return g_strdup ("application/x-compressed-tar;application/x-xz-compressed-tar"); +-} +- +-void +-backend_run (PkBackend *backend, PkStatusEnum status, PkBackendThreadFunc func) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (func != NULL); +- +- if (cancellable != NULL) { +- g_warning ("pacman: cancellable was not NULL"); +- g_object_unref (cancellable); +- } +- cancellable = g_cancellable_new (); +- pk_backend_set_allow_cancel (backend, TRUE); +- +- pk_backend_set_status (backend, status); +- pk_backend_thread_create (backend, func); +-} +- +-/** +- * backend_cancel: +- **/ +-static void +-backend_cancel (PkBackend *backend) +-{ +- g_return_if_fail (backend != NULL); +- +- if (cancellable != NULL) { +- g_cancellable_cancel (cancellable); +- } +-} +- +-gboolean +-backend_cancelled (PkBackend *backend) +-{ +- g_return_val_if_fail (cancellable != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- if (g_cancellable_is_cancelled (cancellable)) { +- pk_backend_set_status (backend, PK_STATUS_ENUM_CANCEL); +- return TRUE; +- } else { +- return FALSE; +- } +-} +- +-void +-backend_finished (PkBackend *backend) +-{ +- g_return_if_fail (backend != NULL); +- +- pk_backend_set_allow_cancel (backend, FALSE); +- if (cancellable != NULL) { +- g_object_unref (cancellable); +- cancellable = NULL; +- } +- +- pk_backend_thread_finished (backend); +-} +- +-PK_BACKEND_OPTIONS ( +- "pacman", /* description */ +- "Jonathan Conder ", /* author */ +- backend_initialize, /* initialize */ +- backend_destroy, /* destroy */ +- backend_get_groups, /* get_groups */ +- backend_get_filters, /* get_filters */ +- NULL, /* get_roles */ +- backend_get_mime_types, /* get_mime_types */ +- backend_cancel, /* cancel */ +- backend_download_packages, /* download_packages */ +- NULL, /* get_categories */ +- backend_get_depends, /* get_depends */ +- backend_get_details, /* get_details */ +- NULL, /* get_distro_upgrades */ +- backend_get_files, /* get_files */ +- backend_get_packages, /* get_packages */ +- backend_get_repo_list, /* get_repo_list */ +- backend_get_requires, /* get_requires */ +- backend_get_update_detail, /* get_update_detail */ +- backend_get_updates, /* get_updates */ +- backend_install_files, /* install_files */ +- backend_install_packages, /* install_packages */ +- NULL, /* install_signature */ +- backend_refresh_cache, /* refresh_cache */ +- backend_remove_packages, /* remove_packages */ +- backend_repo_enable, /* repo_enable */ +- NULL, /* repo_set_data */ +- backend_resolve, /* resolve */ +- NULL, /* rollback */ +- backend_search_details, /* search_details */ +- backend_search_files, /* search_files */ +- backend_search_groups, /* search_groups */ +- backend_search_names, /* search_names */ +- backend_update_packages, /* update_packages */ +- NULL, /* update_system */ +- backend_what_provides, /* what_provides */ +- backend_simulate_install_files, /* simulate_install_files */ +- backend_simulate_install_packages, /* simulate_install_packages */ +- backend_simulate_remove_packages, /* simulate_remove_packages */ +- backend_simulate_update_packages, /* simulate_update_packages */ +- NULL, /* upgrade_packages */ +- NULL, /* transaction_start */ +- NULL /* transaction_stop */ +-); +diff --git a/backends/pacman/backend-pacman.h b/backends/pacman/backend-pacman.h +deleted file mode 100644 +index 0d7b89b..0000000 +--- a/backends/pacman/backend-pacman.h ++++ /dev/null +@@ -1,35 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include +-#include +- +-extern PacmanManager *pacman; +-extern GCancellable *cancellable; +- +-void backend_run (PkBackend *backend, +- PkStatusEnum status, +- PkBackendThreadFunc func); +-gboolean backend_cancelled (PkBackend *backend); +-void backend_finished (PkBackend *backend); +diff --git a/backends/pacman/backend-remove.c b/backends/pacman/backend-remove.c +deleted file mode 100644 +index b31218b..0000000 +--- a/backends/pacman/backend-remove.c ++++ /dev/null +@@ -1,142 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include "backend-error.h" +-#include "backend-packages.h" +-#include "backend-pacman.h" +-#include "backend-transaction.h" +-#include "backend-remove.h" +- +-static PacmanList * +-backend_remove_list_targets (PkBackend *backend) +-{ +- gchar **package_ids; +- guint iterator; +- PacmanList *list = NULL; +- +- g_return_val_if_fail (backend != NULL, NULL); +- +- package_ids = pk_backend_get_strv (backend, "package_ids"); +- +- g_return_val_if_fail (package_ids != NULL, NULL); +- +- for (iterator = 0; package_ids[iterator] != NULL; ++iterator) { +- gchar **package_id_data = pk_package_id_split (package_ids[iterator]); +- list = pacman_list_add (list, g_strdup (package_id_data[PK_PACKAGE_ID_NAME])); +- g_strfreev (package_id_data); +- } +- +- return list; +-} +- +-static gboolean +-backend_remove_packages_thread (PkBackend *backend) +-{ +- PacmanList *list; +- gboolean allow_deps; +- gboolean autoremove; +- +- PacmanTransaction *transaction = NULL; +- PacmanTransactionFlags flags = PACMAN_TRANSACTION_FLAGS_NONE; +- +- g_return_val_if_fail (backend != NULL, FALSE); +- +- allow_deps = pk_backend_get_bool (backend, "allow_deps"); +- autoremove = pk_backend_get_bool (backend, "autoremove"); +- +- /* remove packages that depend on those to be removed */ +- if (allow_deps) { +- flags |= PACMAN_TRANSACTION_FLAGS_REMOVE_CASCADE; +- } +- /* remove unneeded packages that were required by those to be removed */ +- if (autoremove) { +- flags |= PACMAN_TRANSACTION_FLAGS_REMOVE_RECURSIVE; +- } +- +- /* run the transaction */ +- list = backend_remove_list_targets (backend); +- if (list != NULL) { +- transaction = backend_transaction_run (backend, PACMAN_TRANSACTION_REMOVE, flags, list); +- pacman_list_free_full (list, g_free); +- } +- +- return backend_transaction_finished (backend, transaction); +-} +- +-/** +- * backend_remove_packages: +- **/ +-void +-backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package_ids != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_SETUP, backend_remove_packages_thread); +-} +- +-static gboolean +-backend_simulate_remove_packages_thread (PkBackend *backend) +-{ +- PacmanList *list; +- gboolean autoremove; +- +- PacmanTransaction *transaction = NULL; +- PacmanTransactionFlags flags = PACMAN_TRANSACTION_FLAGS_REMOVE_CASCADE; +- +- g_return_val_if_fail (backend != NULL, FALSE); +- +- autoremove = pk_backend_get_bool (backend, "autoremove"); +- +- /* remove unneeded packages that were required by those to be removed */ +- if (autoremove) { +- flags |= PACMAN_TRANSACTION_FLAGS_REMOVE_RECURSIVE; +- } +- +- /* prepare the transaction */ +- list = backend_remove_list_targets (backend); +- if (list != NULL) { +- transaction = backend_transaction_simulate (backend, PACMAN_TRANSACTION_REMOVE, flags, list); +- pacman_list_free_full (list, g_free); +- +- if (transaction != NULL) { +- /* emit packages that would have been installed or removed */ +- backend_transaction_packages (backend, transaction); +- } +- } +- +- return backend_transaction_finished (backend, transaction); +-} +- +-/** +- * backend_simulate_remove_packages: +- **/ +-void +-backend_simulate_remove_packages (PkBackend *backend, gchar **package_ids, gboolean autoremove) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package_ids != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_SETUP, backend_simulate_remove_packages_thread); +-} +diff --git a/backends/pacman/backend-remove.h b/backends/pacman/backend-remove.h +deleted file mode 100644 +index 90f0374..0000000 +--- a/backends/pacman/backend-remove.h ++++ /dev/null +@@ -1,32 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +- +-void backend_remove_packages (PkBackend *backend, +- gchar **package_ids, +- gboolean allow_deps, +- gboolean autoremove); +-void backend_simulate_remove_packages (PkBackend *backend, +- gchar **package_ids, +- gboolean autoremove); +diff --git a/backends/pacman/backend-repos.c b/backends/pacman/backend-repos.c +deleted file mode 100644 +index 8ef23d9..0000000 +--- a/backends/pacman/backend-repos.c ++++ /dev/null +@@ -1,298 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include "backend-error.h" +-#include "backend-pacman.h" +-#include "backend-repos.h" +- +-PacmanDatabase *local_database = NULL; +-static GHashTable *disabled_repos = NULL; +- +-static GHashTable * +-disabled_repos_new (GError **error) +-{ +- GHashTable *disabled; +- GFile *file; +- +- GFileInputStream *file_stream; +- GDataInputStream *data_stream; +- +- gchar *line; +- GError *e = NULL; +- +- g_debug ("pacman: reading disabled repos from %s", PACMAN_REPO_LIST); +- file = g_file_new_for_path (PACMAN_REPO_LIST); +- file_stream = g_file_read (file, NULL, &e); +- +- if (file_stream == NULL) { +- g_object_unref (file); +- g_propagate_error (error, e); +- return NULL; +- } +- +- disabled = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); +- data_stream = g_data_input_stream_new (G_INPUT_STREAM (file_stream)); +- +- /* read disabled repos line by line, ignoring comments */ +- while ((line = g_data_input_stream_read_line (data_stream, NULL, NULL, &e)) != NULL) { +- g_strstrip (line); +- +- if (*line == '\0' || *line == '#') { +- g_free (line); +- continue; +- } +- +- g_hash_table_insert (disabled, line, GINT_TO_POINTER (1)); +- } +- +- g_object_unref (data_stream); +- g_object_unref (file_stream); +- g_object_unref (file); +- +- if (e != NULL) { +- g_hash_table_unref (disabled); +- g_propagate_error (error, e); +- return NULL; +- } else { +- return disabled; +- } +-} +- +-static gboolean +-disabled_repos_configure (GHashTable *disabled, GError **error) +-{ +- const PacmanList *databases; +- +- g_return_val_if_fail (pacman != NULL, FALSE); +- +- g_debug ("pacman: reading config from %s", PACMAN_CONFIG_FILE); +- +- /* read configuration from pacman config file */ +- if (!pacman_manager_configure (pacman, PACMAN_CONFIG_FILE, error)) { +- return FALSE; +- } +- +- local_database = pacman_manager_get_local_database (pacman); +- +- /* disable disabled repos */ +- for (databases = pacman_manager_get_sync_databases (pacman); databases != NULL; databases = pacman_list_next (databases)) { +- PacmanDatabase *database = (PacmanDatabase *) pacman_list_get (databases); +- const gchar *repo = pacman_database_get_name (database); +- +- if (g_hash_table_lookup (disabled, repo) != NULL) { +- if (!pacman_manager_unregister_database (pacman, database, error)) { +- return FALSE; +- } +- +- /* start again as the list gets invalidated */ +- databases = pacman_manager_get_sync_databases (pacman); +- } +- } +- +- return TRUE; +-} +- +-static void +-disabled_repos_free (GHashTable *disabled) +-{ +- GHashTableIter iter; +- GFile *file; +- +- GFileOutputStream *file_stream; +- GDataOutputStream *data_stream; +- +- const gchar *line = PACMAN_REPO_LIST_HEADER "\n"; +- +- g_return_if_fail (disabled != NULL); +- +- g_debug ("pacman: storing disabled repos in %s", PACMAN_REPO_LIST); +- file = g_file_new_for_path (PACMAN_REPO_LIST); +- file_stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL); +- +- if (file_stream == NULL) { +- g_object_unref (file); +- g_hash_table_unref (disabled); +- return; +- } +- +- g_hash_table_iter_init (&iter, disabled); +- data_stream = g_data_output_stream_new (G_OUTPUT_STREAM (file_stream)); +- +- /* write header, then all disabled repos line by line */ +- if (g_data_output_stream_put_string (data_stream, line, NULL, NULL)) { +- while (g_hash_table_iter_next (&iter, (gpointer *) &line, NULL) && +- g_data_output_stream_put_string (data_stream, line, NULL, NULL) && +- g_data_output_stream_put_string (data_stream, "\n", NULL, NULL)); +- } +- +- g_object_unref (data_stream); +- g_object_unref (file_stream); +- g_object_unref (file); +- g_hash_table_unref (disabled); +-} +- +-gboolean +-backend_initialize_databases (PkBackend *backend, GError **error) +-{ +- g_return_val_if_fail (pacman != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- disabled_repos = disabled_repos_new (error); +- if (disabled_repos == NULL) { +- return FALSE; +- } +- +- if (!disabled_repos_configure (disabled_repos, error)) { +- return FALSE; +- } +- +- return TRUE; +-} +- +-void +-backend_destroy_databases (PkBackend *backend) +-{ +- g_return_if_fail (backend != NULL); +- +- if (disabled_repos != NULL) { +- disabled_repos_free (disabled_repos); +- } +-} +- +-static gboolean +-backend_get_repo_list_thread (PkBackend *backend) +-{ +- const PacmanList *databases; +- GHashTableIter iter; +- gpointer key, value; +- +- g_return_val_if_fail (pacman != NULL, FALSE); +- g_return_val_if_fail (disabled_repos != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- /* emit enabled repos */ +- for (databases = pacman_manager_get_sync_databases (pacman); databases != NULL; databases = pacman_list_next (databases)) { +- PacmanDatabase *database = (PacmanDatabase *) pacman_list_get (databases); +- const gchar *repo = pacman_database_get_name (database); +- +- if (backend_cancelled (backend)) { +- break; +- } else { +- pk_backend_repo_detail (backend, repo, repo, TRUE); +- } +- } +- +- /* emit disabled repos */ +- g_hash_table_iter_init (&iter, disabled_repos); +- while (g_hash_table_iter_next (&iter, &key, &value)) { +- const gchar *repo = (const gchar *) key; +- +- if (backend_cancelled (backend)) { +- break; +- } else { +- pk_backend_repo_detail (backend, repo, repo, FALSE); +- } +- } +- +- backend_finished (backend); +- return TRUE; +-} +- +-/** +- * backend_get_repo_list: +- **/ +-void +-backend_get_repo_list (PkBackend *backend, PkBitfield filters) +-{ +- g_return_if_fail (backend != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_get_repo_list_thread); +-} +- +-static gboolean +-backend_repo_enable_thread (PkBackend *backend) +-{ +- GError *error = NULL; +- +- const gchar *repo; +- gboolean enabled; +- +- g_return_val_if_fail (pacman != NULL, FALSE); +- g_return_val_if_fail (disabled_repos != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- repo = pk_backend_get_string (backend, "repo_id"); +- enabled = pk_backend_get_bool (backend, "enabled"); +- +- g_return_val_if_fail (repo != NULL, FALSE); +- +- if (enabled) { +- /* check that repo is indeed disabled */ +- if (g_hash_table_remove (disabled_repos, repo)) { +- /* reload configuration to preserve the correct order */ +- if (disabled_repos_configure (disabled_repos, &error)) { +- pk_backend_repo_list_changed (backend); +- } else { +- backend_error (backend, error); +- pk_backend_thread_finished (backend); +- return FALSE; +- } +- } else { +- pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, "Could not find repo [%s]", repo); +- pk_backend_thread_finished (backend); +- return FALSE; +- } +- } else { +- PacmanDatabase *database = pacman_manager_find_sync_database (pacman, repo); +- +- if (database != NULL) { +- if (pacman_manager_unregister_database (pacman, database, &error)) { +- g_hash_table_insert (disabled_repos, g_strdup (repo), GINT_TO_POINTER (1)); +- } else { +- backend_error (backend, error); +- pk_backend_thread_finished (backend); +- return FALSE; +- } +- } else { +- pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, "Could not find repo [%s]", repo); +- pk_backend_thread_finished (backend); +- return FALSE; +- } +- } +- +- pk_backend_thread_finished (backend); +- return TRUE; +-} +- +-/** +- * backend_repo_enable: +- **/ +-void +-backend_repo_enable (PkBackend *backend, const gchar *repo, gboolean enabled) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (repo != NULL); +- +- pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_thread_create (backend, backend_repo_enable_thread); +-} +diff --git a/backends/pacman/backend-repos.h b/backends/pacman/backend-repos.h +deleted file mode 100644 +index 7faba0c..0000000 +--- a/backends/pacman/backend-repos.h ++++ /dev/null +@@ -1,37 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include +- +-extern PacmanDatabase *local_database; +- +-gboolean backend_initialize_databases (PkBackend *backend, +- GError **error); +-void backend_destroy_databases (PkBackend *backend); +- +-void backend_get_repo_list (PkBackend *backend, +- PkBitfield filters); +-void backend_repo_enable (PkBackend *backend, +- const gchar *repo, +- gboolean enabled); +diff --git a/backends/pacman/backend-search.c b/backends/pacman/backend-search.c +deleted file mode 100644 +index 32b4df8..0000000 +--- a/backends/pacman/backend-search.c ++++ /dev/null +@@ -1,479 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include +-#include "backend-error.h" +-#include "backend-groups.h" +-#include "backend-packages.h" +-#include "backend-pacman.h" +-#include "backend-repos.h" +-#include "backend-search.h" +- +-static gpointer +-backend_pattern_needle (const gchar *needle, GError **error) +-{ +- return (gpointer) needle; +-} +- +-static gpointer +-backend_pattern_regex (const gchar *needle, GError **error) +-{ +- gchar *pattern; +- GRegex *regex; +- +- g_return_val_if_fail (needle != NULL, NULL); +- +- pattern = g_regex_escape_string (needle, -1); +- regex = g_regex_new (pattern, G_REGEX_CASELESS, 0, error); +- g_free (pattern); +- +- return regex; +-} +- +-static gpointer +-backend_pattern_chroot (const gchar *needle, GError **error) +-{ +- g_return_val_if_fail (pacman != NULL, FALSE); +- g_return_val_if_fail (needle != NULL, NULL); +- +- if (G_IS_DIR_SEPARATOR (*needle)) { +- const gchar *file = needle, *path = pacman_manager_get_root_path (pacman); +- +- /* adjust needle to the correct prefix */ +- while (*file++ == *path++) { +- if (*path == '\0') { +- needle = file - 1; +- break; +- } else if (*file == '\0') { +- break; +- } +- } +- } +- +- return (gpointer) needle; +-} +- +-static gboolean +-backend_match_all (PacmanPackage *package, gpointer pattern) +-{ +- g_return_val_if_fail (package != NULL, FALSE); +- g_return_val_if_fail (pattern != NULL, FALSE); +- +- /* match all packages */ +- return TRUE; +-} +- +-static gboolean +-backend_match_details (PacmanPackage *package, gpointer pattern) +-{ +- const gchar *description; +- PacmanDatabase *database; +- const PacmanList *licenses; +- +- GRegex *regex = (GRegex *) pattern; +- +- g_return_val_if_fail (package != NULL, FALSE); +- g_return_val_if_fail (regex != NULL, FALSE); +- +- /* match the name first... */ +- if (g_regex_match (regex, pacman_package_get_name (package), 0, NULL)) { +- return TRUE; +- } +- +- /* ... then the description... */ +- description = pacman_package_get_description (package); +- if (description != NULL && g_regex_match (regex, description, 0, NULL)) { +- return TRUE; +- } +- +- /* ... then the database... */ +- database = pacman_package_get_database (package); +- if (database != NULL && g_regex_match (regex, pacman_database_get_name (database), G_REGEX_MATCH_ANCHORED, NULL)) { +- return TRUE; +- } +- +- /* ... then the licenses */ +- for (licenses = pacman_package_get_licenses (package); licenses != NULL; licenses = pacman_list_next (licenses)) { +- const gchar *license = (const gchar *) pacman_list_get (licenses); +- if (g_regex_match (regex, license, G_REGEX_MATCH_ANCHORED, NULL)) { +- return TRUE; +- } +- } +- +- return FALSE; +-} +- +-static gboolean +-backend_match_file (PacmanPackage *package, gpointer pattern) +-{ +- const PacmanList *files; +- const gchar *needle = (const gchar *) pattern; +- +- g_return_val_if_fail (package != NULL, FALSE); +- g_return_val_if_fail (needle != NULL, FALSE); +- +- /* match any file the package contains */ +- if (G_IS_DIR_SEPARATOR (*needle)) { +- for (files = pacman_package_get_files (package); files != NULL; files = pacman_list_next (files)) { +- const gchar *file = (const gchar *) pacman_list_get (files); +- +- /* match the full path of file */ +- if (g_strcmp0 (file, needle + 1) == 0) { +- return TRUE; +- } +- } +- } else { +- for (files = pacman_package_get_files (package); files != NULL; files = pacman_list_next (files)) { +- const gchar *file = (const gchar *) pacman_list_get (files); +- file = strrchr (file, G_DIR_SEPARATOR); +- +- /* match the basename of file */ +- if (file != NULL && g_strcmp0 (file + 1, needle) == 0) { +- return TRUE; +- } +- } +- } +- +- return FALSE; +-} +- +-static gboolean +-backend_match_group (PacmanPackage *package, gpointer pattern) +-{ +- const gchar *needle = (const gchar *) pattern; +- +- g_return_val_if_fail (package != NULL, FALSE); +- g_return_val_if_fail (needle != NULL, FALSE); +- +- /* match the group the package is in */ +- return g_strcmp0 (needle, pacman_package_get_group (package)) == 0; +-} +- +-static gboolean +-backend_match_name (PacmanPackage *package, gpointer pattern) +-{ +- GRegex *regex = (GRegex *) pattern; +- +- g_return_val_if_fail (package != NULL, FALSE); +- g_return_val_if_fail (regex != NULL, FALSE); +- +- /* match the name of the package */ +- return g_regex_match (regex, pacman_package_get_name (package), 0, NULL); +-} +- +-static gboolean +-backend_match_provides (PacmanPackage *package, gpointer pattern) +-{ +- /* TODO: implement GStreamer codecs, Pango fonts, etc. */ +- const PacmanList *provides; +- +- g_return_val_if_fail (package != NULL, FALSE); +- g_return_val_if_fail (pattern != NULL, FALSE); +- +- /* match features provided by package */ +- for (provides = pacman_package_get_provides (package); provides != NULL; provides = pacman_list_next (provides)) { +- const gchar *needle = (const gchar *) pattern, *name = (const gchar *) pacman_list_get (provides); +- +- while (*needle == *name && *needle != '\0') { +- ++needle; +- ++name; +- } +- +- if (*needle == '\0' && (*name == '\0' || *name == '=')) { +- return TRUE; +- } +- } +- +- return FALSE; +-} +- +-typedef enum { +- SEARCH_TYPE_ALL, +- SEARCH_TYPE_DETAILS, +- SEARCH_TYPE_FILES, +- SEARCH_TYPE_GROUP, +- SEARCH_TYPE_NAME, +- SEARCH_TYPE_PROVIDES, +- SEARCH_TYPE_LAST +-} SearchType; +- +-typedef gpointer (*PatternFunc) (const gchar *needle, GError **error); +-typedef gboolean (*MatchFunc) (PacmanPackage *package, gpointer pattern); +- +-static PatternFunc pattern_funcs[] = { +- backend_pattern_needle, +- backend_pattern_regex, +- backend_pattern_chroot, +- backend_pattern_needle, +- backend_pattern_regex, +- backend_pattern_needle +-}; +- +-static GDestroyNotify pattern_frees[] = { +- NULL, +- (GDestroyNotify) g_regex_unref, +- NULL, +- NULL, +- (GDestroyNotify) g_regex_unref, +- NULL +-}; +- +-static MatchFunc match_funcs[] = { +- backend_match_all, +- backend_match_details, +- backend_match_file, +- backend_match_group, +- backend_match_name, +- backend_match_provides +-}; +- +-static gboolean +-pacman_package_is_installed (PacmanPackage *package) +-{ +- PacmanPackage *installed; +- +- g_return_val_if_fail (local_database != NULL, FALSE); +- g_return_val_if_fail (package != NULL, FALSE); +- +- /* find an installed package with the same name */ +- installed = pacman_database_find_package (local_database, pacman_package_get_name (package)); +- if (installed == NULL) { +- return FALSE; +- } +- +- /* make sure the installed version is the same */ +- if (pacman_package_compare_version (pacman_package_get_version (installed), pacman_package_get_version (package)) != 0) { +- return FALSE; +- } +- +- /* make sure the installed arch is the same */ +- if (g_strcmp0 (pacman_package_get_arch (installed), pacman_package_get_arch (package)) != 0) { +- return FALSE; +- } +- +- return TRUE; +-} +- +-static void +-backend_search_database (PkBackend *backend, PacmanDatabase *database, MatchFunc match, const PacmanList *patterns) +-{ +- const PacmanList *packages, *list; +- +- g_return_if_fail (backend != NULL); +- g_return_if_fail (database != NULL); +- g_return_if_fail (match != NULL); +- +- /* emit packages that match all search terms */ +- for (packages = pacman_database_get_packages (database); packages != NULL; packages = pacman_list_next (packages)) { +- PacmanPackage *package = (PacmanPackage *) pacman_list_get (packages); +- +- if (backend_cancelled (backend)) { +- break; +- } +- +- for (list = patterns; list != NULL; list = pacman_list_next (list)) { +- if (!match (package, pacman_list_get (list))) { +- break; +- } +- } +- +- /* all search terms matched */ +- if (list == NULL) { +- if (database == local_database) { +- backend_package (backend, package, PK_INFO_ENUM_INSTALLED); +- } else if (!pacman_package_is_installed (package)) { +- backend_package (backend, package, PK_INFO_ENUM_AVAILABLE); +- } +- } +- } +-} +- +-static gboolean +-backend_search_thread (PkBackend *backend) +-{ +- gchar **search; +- SearchType search_type; +- +- PatternFunc pattern_func; +- GDestroyNotify pattern_free; +- MatchFunc match_func; +- +- PkBitfield filters; +- gboolean search_installed; +- gboolean search_not_installed; +- +- guint iterator; +- PacmanList *patterns = NULL; +- GError *error = NULL; +- +- g_return_val_if_fail (pacman != NULL, FALSE); +- g_return_val_if_fail (local_database != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- search = pk_backend_get_strv (backend, "search"); +- search_type = (SearchType) pk_backend_get_uint (backend, "search-type"); +- +- g_return_val_if_fail (search != NULL, FALSE); +- g_return_val_if_fail (search_type < SEARCH_TYPE_LAST, FALSE); +- +- pattern_func = pattern_funcs[search_type]; +- pattern_free = pattern_frees[search_type]; +- match_func = match_funcs[search_type]; +- +- g_return_val_if_fail (pattern_func != NULL, FALSE); +- g_return_val_if_fail (match_func != NULL, FALSE); +- +- filters = pk_backend_get_uint (backend, "filters"); +- search_installed = pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED); +- search_not_installed = pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED); +- +- /* convert search terms to the pattern requested */ +- for (iterator = 0; search[iterator] != NULL; ++iterator) { +- gpointer pattern = pattern_func (search[iterator], &error); +- +- if (pattern != NULL) { +- patterns = pacman_list_add (patterns, pattern); +- } else { +- backend_error (backend, error); +- if (pattern_free != NULL) { +- pacman_list_free_full (patterns, pattern_free); +- } else { +- pacman_list_free (patterns); +- } +- backend_finished (backend); +- return FALSE; +- } +- } +- +- /* find installed packages first */ +- if (!search_not_installed) { +- backend_search_database (backend, local_database, match_func, patterns); +- } +- +- if (!search_installed) { +- const PacmanList *databases; +- +- for (databases = pacman_manager_get_sync_databases (pacman); databases != NULL; databases = pacman_list_next (databases)) { +- PacmanDatabase *database = (PacmanDatabase *) pacman_list_get (databases); +- +- if (backend_cancelled (backend)) { +- break; +- } +- +- backend_search_database (backend, database, match_func, patterns); +- } +- } +- +- if (pattern_free != NULL) { +- pacman_list_free_full (patterns, pattern_free); +- } else { +- pacman_list_free (patterns); +- } +- backend_finished (backend); +- return TRUE; +-} +- +-/** +- * backend_get_packages: +- **/ +-void +-backend_get_packages (PkBackend *backend, PkBitfield filters) +-{ +- g_return_if_fail (backend != NULL); +- +- /* provide a dummy needle */ +- pk_backend_set_strv (backend, "search", g_strsplit ("", ";", 0)); +- +- pk_backend_set_uint (backend, "search-type", SEARCH_TYPE_ALL); +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_search_thread); +-} +- +-/** +- * backend_search_details: +- **/ +-void +-backend_search_details (PkBackend *backend, PkBitfield filters, gchar **values) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (values != NULL); +- +- pk_backend_set_uint (backend, "search-type", SEARCH_TYPE_DETAILS); +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_search_thread); +-} +- +-/** +- * backend_search_files: +- **/ +-void +-backend_search_files (PkBackend *backend, PkBitfield filters, gchar **values) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (values != NULL); +- +- /* speed up search by restricting it to local database */ +- pk_bitfield_add (filters, PK_FILTER_ENUM_INSTALLED); +- pk_backend_set_uint (backend, "filters", filters); +- +- pk_backend_set_uint (backend, "search-type", SEARCH_TYPE_FILES); +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_search_thread); +-} +- +-/** +- * backend_search_groups: +- **/ +-void +-backend_search_groups (PkBackend *backend, PkBitfield filters, gchar **values) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (values != NULL); +- +- pk_backend_set_uint (backend, "search-type", SEARCH_TYPE_GROUP); +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_search_thread); +-} +- +-/** +- * backend_search_names: +- **/ +-void +-backend_search_names (PkBackend *backend, PkBitfield filters, gchar **values) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (values != NULL); +- +- pk_backend_set_uint (backend, "search-type", SEARCH_TYPE_NAME); +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_search_thread); +-} +- +-/** +- * backend_what_provides: +- **/ +-void +-backend_what_provides (PkBackend *backend, PkBitfield filters, PkProvidesEnum provides, gchar **values) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (values != NULL); +- +- pk_backend_set_uint (backend, "search-type", SEARCH_TYPE_PROVIDES); +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_search_thread); +-} +diff --git a/backends/pacman/backend-search.h b/backends/pacman/backend-search.h +deleted file mode 100644 +index c2ce6a0..0000000 +--- a/backends/pacman/backend-search.h ++++ /dev/null +@@ -1,43 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +- +-void backend_get_packages (PkBackend *backend, +- PkBitfield filters); +-void backend_search_details (PkBackend *backend, +- PkBitfield filters, +- gchar **values); +-void backend_search_files (PkBackend *backend, +- PkBitfield filters, +- gchar **values); +-void backend_search_groups (PkBackend *backend, +- PkBitfield filters, +- gchar **values); +-void backend_search_names (PkBackend *backend, +- PkBitfield filters, +- gchar **values); +-void backend_what_provides (PkBackend *backend, +- PkBitfield filters, +- PkProvidesEnum provides, +- gchar **values); +diff --git a/backends/pacman/backend-transaction.c b/backends/pacman/backend-transaction.c +deleted file mode 100644 +index 748760b..0000000 +--- a/backends/pacman/backend-transaction.c ++++ /dev/null +@@ -1,532 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include "backend-error.h" +-#include "backend-packages.h" +-#include "backend-pacman.h" +-#include "backend-repos.h" +-#include "backend-transaction.h" +- +-typedef struct { +- guint complete; +- guint total; +- +- PacmanPackage *package; +- GString *files; +-} BackendDownloadData; +- +-static GHashTable *downloads = NULL; +- +-gboolean +-backend_initialize_downloads (PkBackend *backend, GError **error) +-{ +- g_return_val_if_fail (backend != NULL, FALSE); +- +- downloads = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); +- return TRUE; +-} +- +-void +-backend_destroy_downloads (PkBackend *backend) +-{ +- g_return_if_fail (backend != NULL); +- +- if (downloads != NULL) { +- g_hash_table_unref (downloads); +- } +-} +- +-static void +-transaction_download_end (PacmanTransaction *transaction, BackendDownloadData *download, PkBackend *backend) { +- g_return_if_fail (transaction != NULL); +- g_return_if_fail (download != NULL); +- g_return_if_fail (backend != NULL); +- +- /* emit the finished signal for the old package */ +- backend_package (backend, download->package, PK_INFO_ENUM_FINISHED); +- +- /* emit the list of files downloaded for DownloadPackages */ +- if (download->files != NULL) { +- gchar *package_id, *files; +- +- package_id = pacman_package_make_id (download->package); +- files = g_string_free (download->files, FALSE); +- +- pk_backend_files (backend, package_id, files); +- +- g_free (package_id); +- g_free (files); +- } +- +- download->package = NULL; +- download->files = NULL; +-} +- +-static gchar * +-backend_filename_make_path (PkBackend *backend, const gchar *filename) +-{ +- const gchar *directory; +- +- g_return_val_if_fail (backend != NULL, NULL); +- g_return_val_if_fail (filename != NULL, NULL); +- +- directory = pk_backend_get_string (backend, "directory"); +- +- g_return_val_if_fail (directory != NULL, NULL); +- +- return g_build_filename (directory, filename, NULL); +-} +- +-static void +-transaction_download_start (PacmanTransaction *transaction, BackendDownloadData *download, const gchar *filename, PkBackend *backend) +-{ +- const PacmanList *packages; +- +- g_return_if_fail (transaction != NULL); +- g_return_if_fail (download != NULL); +- g_return_if_fail (filename != NULL); +- g_return_if_fail (backend != NULL); +- +- /* continue or finish downloading the old package */ +- if (download->package != NULL) { +- if (pacman_package_has_filename (download->package, filename)) { +- if (download->files != NULL) { +- gchar *path = backend_filename_make_path (backend, filename); +- g_string_append_printf (download->files, ";%s", path); +- g_free (path); +- } +- return; +- } else { +- transaction_download_end (transaction, download, backend); +- } +- } +- +- /* find a new package for the current file */ +- for (packages = pacman_transaction_get_installs (transaction); packages != NULL; packages = pacman_list_next (packages)) { +- PacmanPackage *package = (PacmanPackage *) pacman_list_get (packages); +- if (pacman_package_has_filename (package, filename)) { +- download->package = package; +- break; +- } +- } +- +- /* emit the downloading signal and start collecting files for the new package */ +- if (download->package != NULL) { +- backend_package (backend, download->package, PK_INFO_ENUM_DOWNLOADING); +- +- /* only emit files downloaded for DownloadPackages */ +- if (pk_backend_get_role (backend) == PK_ROLE_ENUM_DOWNLOAD_PACKAGES) { +- gchar *path = backend_filename_make_path (backend, filename); +- download->files = g_string_new (path); +- g_free (path); +- } +- } +-} +- +-static void +-transaction_download_cb (PacmanTransaction *transaction, const gchar *filename, guint complete, guint total, gpointer user_data) +-{ +- BackendDownloadData *download; +- +- g_return_if_fail (pacman != NULL); +- g_return_if_fail (transaction != NULL); +- g_return_if_fail (user_data != NULL); +- +- download = (BackendDownloadData *) g_hash_table_lookup (downloads, transaction); +- +- if (filename == NULL) { +- if (download == NULL) { +- /* start a new download */ +- download = g_new0 (BackendDownloadData, 1); +- download->complete = complete; +- download->total = total; +- g_hash_table_insert (downloads, transaction, download); +- } else { +- /* finish the current download */ +- if (download->package != NULL) { +- transaction_download_end (transaction, download, (PkBackend *) user_data); +- } +- g_hash_table_remove (downloads, transaction); +- } +- } else { +- guint percentage = 100, sub_percentage = 100; +- +- g_return_if_fail (download != NULL); +- +- if (total > 0) { +- sub_percentage = complete * 100 / total; +- } +- +- if (strstr (filename, ".db.tar.") != NULL) { +- const PacmanList *databases = pacman_manager_get_sync_databases (pacman); +- guint database_total = pacman_list_length (databases); +- +- /* report download progress for databases */ +- if (database_total > 0) { +- percentage = (sub_percentage + download->complete * 100) / database_total; +- } +- +- if (complete == 0) { +- g_debug ("pacman: downloading database %s", filename); +- pk_backend_set_status ((PkBackend *) user_data, PK_STATUS_ENUM_REFRESH_CACHE); +- } +- +- if (complete == total) { +- download->complete += 1; +- } +- } else { +- /* report download progress for package or delta files */ +- if (download->total > 0) { +- percentage = (download->complete + complete) * 100 / download->total; +- } +- +- if (complete == 0) { +- g_debug ("pacman: downloading package %s", filename); +- pk_backend_set_status ((PkBackend *) user_data, PK_STATUS_ENUM_DOWNLOAD); +- transaction_download_start (transaction, download, filename, (PkBackend *) user_data); +- } +- +- if (complete == total) { +- download->complete += complete; +- } +- } +- +- pk_backend_set_sub_percentage ((PkBackend *) user_data, sub_percentage); +- pk_backend_set_percentage ((PkBackend *) user_data, percentage); +- } +-} +- +-static void +-transaction_progress_cb (PacmanTransaction *transaction, PacmanTransactionProgress type, const gchar *target, guint percent, guint current, guint targets, gpointer user_data) +-{ +- g_return_if_fail (transaction != NULL); +- g_return_if_fail (user_data != NULL); +- +- g_return_if_fail (percent >= 0); +- g_return_if_fail (percent <= 100); +- g_return_if_fail (current >= 1); +- g_return_if_fail (current <= targets); +- +- /* update transaction progress */ +- switch (type) { +- case PACMAN_TRANSACTION_PROGRESS_INSTALL: +- case PACMAN_TRANSACTION_PROGRESS_UPGRADE: +- case PACMAN_TRANSACTION_PROGRESS_REMOVE: +- case PACMAN_TRANSACTION_PROGRESS_FILE_CONFLICT_CHECK: +- { +- g_debug ("pacman: progress for %s (%u of %u) is %u%%", target, current, targets, percent); +- pk_backend_set_sub_percentage ((PkBackend *) user_data, percent); +- pk_backend_set_percentage ((PkBackend *) user_data, (percent + (current - 1) * 100) / targets); +- break; +- } +- default: +- g_debug ("pacman: progress of type %d (%u of %u) is %u%%", type, current, targets, percent); +- break; +- } +-} +- +-static gboolean +-transaction_question_cb (PacmanTransaction *transaction, PacmanTransactionQuestion question, const gchar *message, gpointer user_data) +-{ +- g_return_val_if_fail (transaction != NULL, FALSE); +- g_return_val_if_fail (user_data != NULL, FALSE); +- +- switch (question) { +- case PACMAN_TRANSACTION_QUESTION_INSTALL_IGNORE_PACKAGE: +- { +- PkRoleEnum role = pk_backend_get_role ((PkBackend *) user_data); +- if (role == PK_ROLE_ENUM_INSTALL_PACKAGES) { +- gchar *packages = pacman_package_make_list (pacman_transaction_get_marked_packages (transaction)); +- gchar *warning = g_strdup_printf ("The following packages were marked as ignored:\n%s\n", packages); +- +- /* ignored packages are blocked in updates, can be explicitly installed */ +- g_warning ("pacman: %s", warning); +- backend_message ((PkBackend *) user_data, warning); +- +- g_free (warning); +- g_free (packages); +- return TRUE; +- } else if (role == PK_ROLE_ENUM_DOWNLOAD_PACKAGES || role == PK_ROLE_ENUM_SIMULATE_INSTALL_PACKAGES) { +- return TRUE; +- } else { +- return FALSE; +- } +- } +- case PACMAN_TRANSACTION_QUESTION_SKIP_UNRESOLVABLE_PACKAGES: +- case PACMAN_TRANSACTION_QUESTION_REMOVE_HOLD_PACKAGES: +- case PACMAN_TRANSACTION_QUESTION_SYNC_FIRST: +- /* none of these actions are safe */ +- g_warning ("pacman: ignoring question '%s'", message); +- return FALSE; +- +- case PACMAN_TRANSACTION_QUESTION_REPLACE_PACKAGE: +- case PACMAN_TRANSACTION_QUESTION_REMOVE_CONFLICTING_PACKAGE: +- case PACMAN_TRANSACTION_QUESTION_INSTALL_OLDER_PACKAGE: +- case PACMAN_TRANSACTION_QUESTION_DELETE_CORRUPTED_PACKAGE: +- /* these actions are mostly harmless */ +- g_warning ("pacman: confirming question '%s'", message); +- return TRUE; +- +- default: +- g_warning ("pacman: unrecognised question '%s'", message); +- return FALSE; +- } +-} +- +-static void +-transaction_status_cb (PacmanTransaction *transaction, PacmanTransactionStatus status, const gchar *message, gpointer user_data) +-{ +- PkStatusEnum state; +- PkInfoEnum info; +- +- g_return_if_fail (transaction != NULL); +- g_return_if_fail (user_data != NULL); +- +- /* figure out the backend status and package info */ +- switch (status) { +- case PACMAN_TRANSACTION_STATUS_INSTALL_START: +- state = PK_STATUS_ENUM_INSTALL; +- info = PK_INFO_ENUM_INSTALLING; +- break; +- +- case PACMAN_TRANSACTION_STATUS_UPGRADE_START: +- if (pk_backend_get_role ((PkBackend *) user_data) == PK_ROLE_ENUM_INSTALL_FILES) { +- state = PK_STATUS_ENUM_INSTALL; +- info = PK_INFO_ENUM_INSTALLING; +- } else { +- state = PK_STATUS_ENUM_UPDATE; +- info = PK_INFO_ENUM_UPDATING; +- } +- break; +- +- case PACMAN_TRANSACTION_STATUS_REMOVE_START: +- state = PK_STATUS_ENUM_REMOVE; +- info = PK_INFO_ENUM_REMOVING; +- break; +- +- case PACMAN_TRANSACTION_STATUS_INSTALL_END: +- case PACMAN_TRANSACTION_STATUS_UPGRADE_END: +- case PACMAN_TRANSACTION_STATUS_REMOVE_END: +- state = PK_STATUS_ENUM_UNKNOWN; +- info = PK_INFO_ENUM_FINISHED; +- break; +- +- case PACMAN_TRANSACTION_STATUS_DEPENDENCY_CHECK_START: +- case PACMAN_TRANSACTION_STATUS_DEPENDENCY_RESOLVE_START: +- state = PK_STATUS_ENUM_DEP_RESOLVE; +- info = PK_INFO_ENUM_UNKNOWN; +- break; +- +- case PACMAN_TRANSACTION_STATUS_FILE_CONFLICT_CHECK_START: +- case PACMAN_TRANSACTION_STATUS_CONFLICT_CHECK_START: +- case PACMAN_TRANSACTION_STATUS_PACKAGE_INTEGRITY_CHECK_START: +- case PACMAN_TRANSACTION_STATUS_DELTA_INTEGRITY_CHECK_START: +- state = PK_STATUS_ENUM_TEST_COMMIT; +- info = PK_INFO_ENUM_UNKNOWN; +- break; +- +- default: +- state = PK_STATUS_ENUM_UNKNOWN; +- info = PK_INFO_ENUM_UNKNOWN; +- g_debug ("pacman: %s", message); +- break; +- } +- +- /* update the backend status */ +- if (state != PK_STATUS_ENUM_UNKNOWN) { +- pk_backend_set_status ((PkBackend *) user_data, state); +- } +- +- /* update the package info */ +- if (info != PK_INFO_ENUM_UNKNOWN) { +- const PacmanList *packages; +- +- for (packages = pacman_transaction_get_marked_packages (transaction); packages != NULL; packages = pacman_list_next (packages)) { +- PacmanPackage *package; +- +- /* only report the old versions */ +- if (status == PACMAN_TRANSACTION_STATUS_UPGRADE_START || status == PACMAN_TRANSACTION_STATUS_UPGRADE_END) { +- packages = pacman_list_next (packages); +- if (packages == NULL) { +- break; +- } +- } +- +- package = (PacmanPackage *) pacman_list_get (packages); +- backend_package ((PkBackend *) user_data, package, info); +- } +- } +-} +- +-static void +-transaction_cancelled_cb (GCancellable *object, gpointer user_data) +-{ +- g_return_if_fail (user_data != NULL); +- +- pacman_transaction_cancel ((PacmanTransaction *) user_data, NULL); +-} +- +-PacmanTransaction * +-backend_transaction_simulate (PkBackend *backend, PacmanTransactionType type, guint32 flags, const PacmanList *targets) +-{ +- PacmanTransaction *transaction; +- GError *error = NULL; +- +- g_return_val_if_fail (pacman != NULL, NULL); +- g_return_val_if_fail (cancellable != NULL, NULL); +- g_return_val_if_fail (backend != NULL, NULL); +- g_return_val_if_fail (type < PACMAN_TRANSACTION_LAST, NULL); +- +- switch (type) { +- case PACMAN_TRANSACTION_INSTALL: +- transaction = pacman_manager_install (pacman, flags, &error); +- break; +- case PACMAN_TRANSACTION_MODIFY: +- transaction = pacman_manager_modify (pacman, flags, &error); +- break; +- case PACMAN_TRANSACTION_REMOVE: +- transaction = pacman_manager_remove (pacman, flags, &error); +- break; +- case PACMAN_TRANSACTION_SYNC: +- transaction = pacman_manager_sync (pacman, flags, &error); +- break; +- case PACMAN_TRANSACTION_UPDATE: +- transaction = pacman_manager_update (pacman, flags, &error); +- break; +- default: +- g_return_val_if_reached (NULL); +- } +- +- if (transaction == NULL) { +- backend_error (backend, error); +- return NULL; +- } +- +- g_signal_connect (transaction, "download", G_CALLBACK (transaction_download_cb), backend); +- g_signal_connect (transaction, "progress", G_CALLBACK (transaction_progress_cb), backend); +- g_signal_connect (transaction, "question", G_CALLBACK (transaction_question_cb), backend); +- g_signal_connect (transaction, "status", G_CALLBACK (transaction_status_cb), backend); +- +- if (g_cancellable_connect (cancellable, G_CALLBACK (transaction_cancelled_cb), transaction, NULL) == 0 && backend_cancelled (backend)) { +- return transaction; +- } +- +- if (!pacman_transaction_prepare (transaction, targets, &error)) { +- backend_error (backend, error); +- g_object_unref (transaction); +- return NULL; +- } +- +- return transaction; +-} +- +-PacmanTransaction * +-backend_transaction_run (PkBackend *backend, PacmanTransactionType type, guint32 flags, const PacmanList *targets) +-{ +- PacmanTransaction *transaction; +- +- g_return_val_if_fail (backend != NULL, NULL); +- +- transaction = backend_transaction_simulate (backend, type, flags, targets); +- +- return backend_transaction_commit (backend, transaction); +-} +- +-void +-backend_transaction_packages (PkBackend *backend, PacmanTransaction *transaction) +-{ +- const PacmanList *installs, *removes; +- PkInfoEnum info; +- +- g_return_if_fail (local_database != NULL); +- g_return_if_fail (backend != NULL); +- g_return_if_fail (transaction != NULL); +- +- /* emit packages that would have been installed */ +- for (installs = pacman_transaction_get_installs (transaction); installs != NULL; installs = pacman_list_next (installs)) { +- PacmanPackage *install = (PacmanPackage *) pacman_list_get (installs); +- +- if (backend_cancelled (backend)) { +- break; +- } else { +- const gchar *name = pacman_package_get_name (install); +- if (pacman_database_find_package (local_database, name) != NULL) { +- backend_package (backend, install, PK_INFO_ENUM_UPDATING); +- } else { +- backend_package (backend, install, PK_INFO_ENUM_INSTALLING); +- } +- } +- } +- +- if (pk_backend_get_role (backend) == PK_ROLE_ENUM_SIMULATE_UPDATE_PACKAGES) { +- info = PK_INFO_ENUM_OBSOLETING; +- } else { +- info = PK_INFO_ENUM_REMOVING; +- } +- +- /* emit packages that would have been removed */ +- for (removes = pacman_transaction_get_removes (transaction); removes != NULL; removes = pacman_list_next (removes)) { +- PacmanPackage *remove = (PacmanPackage *) pacman_list_get (removes); +- +- if (backend_cancelled (backend)) { +- break; +- } else { +- backend_package (backend, remove, info); +- } +- } +-} +- +-PacmanTransaction * +-backend_transaction_commit (PkBackend *backend, PacmanTransaction *transaction) +-{ +- GError *error = NULL; +- +- if (transaction != NULL && !backend_cancelled (backend)) { +- pk_backend_set_status (backend, PK_STATUS_ENUM_RUNNING); +- +- if (!pacman_transaction_commit (transaction, &error)) { +- backend_error (backend, error); +- g_hash_table_remove (downloads, transaction); +- g_object_unref (transaction); +- return NULL; +- } +- } +- +- return transaction; +-} +- +-gboolean +-backend_transaction_finished (PkBackend *backend, PacmanTransaction *transaction) +-{ +- g_return_val_if_fail (backend != NULL, FALSE); +- +- if (transaction != NULL) { +- g_object_unref (transaction); +- backend_finished (backend); +- return TRUE; +- } else { +- backend_finished (backend); +- return FALSE; +- } +-} +diff --git a/backends/pacman/backend-transaction.h b/backends/pacman/backend-transaction.h +deleted file mode 100644 +index a7db49a..0000000 +--- a/backends/pacman/backend-transaction.h ++++ /dev/null +@@ -1,54 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include +- +-typedef enum { +- PACMAN_TRANSACTION_INSTALL, +- PACMAN_TRANSACTION_MODIFY, +- PACMAN_TRANSACTION_REMOVE, +- PACMAN_TRANSACTION_SYNC, +- PACMAN_TRANSACTION_UPDATE, +- PACMAN_TRANSACTION_LAST +-} PacmanTransactionType; +- +-gboolean backend_initialize_downloads (PkBackend *backend, +- GError **error); +-void backend_destroy_downloads (PkBackend *backend); +- +-PacmanTransaction *backend_transaction_simulate (PkBackend *backend, +- PacmanTransactionType type, +- guint32 flags, +- const PacmanList *targets); +-PacmanTransaction *backend_transaction_run (PkBackend *backend, +- PacmanTransactionType type, +- guint32 flags, +- const PacmanList *targets); +- +-void backend_transaction_packages (PkBackend *backend, +- PacmanTransaction *transaction); +-PacmanTransaction *backend_transaction_commit (PkBackend *backend, +- PacmanTransaction *transaction); +-gboolean backend_transaction_finished (PkBackend *backend, +- PacmanTransaction *transaction); +diff --git a/backends/pacman/backend-update.c b/backends/pacman/backend-update.c +deleted file mode 100644 +index a34eb05..0000000 +--- a/backends/pacman/backend-update.c ++++ /dev/null +@@ -1,394 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +-#include +-#include +-#include "backend-error.h" +-#include "backend-pacman.h" +-#include "backend-packages.h" +-#include "backend-repos.h" +-#include "backend-transaction.h" +-#include "backend-update.h" +- +-static gchar * +-pacman_package_make_replaces_ids (PacmanPackage *package) +-{ +- const PacmanList *list; +- GString *string = NULL; +- +- g_return_val_if_fail (local_database != NULL, NULL); +- g_return_val_if_fail (package != NULL, NULL); +- +- /* make a list of the packages that package replaces */ +- for (list = pacman_package_get_replaces (package); list != NULL; list = pacman_list_next (list)) { +- const gchar *name = pacman_list_get (list); +- PacmanPackage *replaces = pacman_database_find_package (local_database, name); +- +- if (replaces != NULL) { +- gchar *package_id = pacman_package_make_id (replaces); +- if (string == NULL) { +- string = g_string_new (package_id); +- } else { +- g_string_append_printf (string, "&%s", package_id); +- } +- g_free (package_id); +- } +- } +- +- if (string != NULL) { +- return g_string_free (string, FALSE); +- } else { +- return NULL; +- } +-} +- +-static gchar * +-pacman_package_make_vendor_url (PacmanPackage *package) +-{ +- GString *string = g_string_new (""); +-#ifdef PACMAN_PACKAGE_URL +- const gchar *name, *arch, *repo, *url; +-#else +- const gchar *url; +-#endif +- +- g_return_val_if_fail (package != NULL, NULL); +- +- /* grab the URL of the package... */ +- url = pacman_package_get_url (package); +- if (url != NULL) { +- g_string_append_printf (string, "%s;Package website;", url); +- } +- +-#ifdef PACMAN_PACKAGE_URL +- /* ... and construct the distro URL if possible */ +- name = pacman_package_get_name (package); +- arch = pacman_package_get_arch (package); +- repo = pacman_database_get_name (pacman_package_get_database (package)); +- +- g_string_append_printf (string, PACMAN_PACKAGE_URL ";Distribution website;", repo, arch, name); +-#endif +- +- g_string_truncate (string, string->len - 1); +- return g_string_free (string, FALSE); +-} +- +-static gint +-pacman_package_compare_pkgver (PacmanPackage *a, PacmanPackage *b) +-{ +- gint result; +- const gchar *version_a, *version_b, *last_a, *last_b; +- gchar *pkgver_a, *pkgver_b; +- +- g_return_val_if_fail (a != NULL, (b == NULL) ? 0 : -1); +- g_return_val_if_fail (b != NULL, 1); +- +- version_a = pacman_package_get_version (a); +- version_b = pacman_package_get_version (b); +- +- last_a = strrchr (version_a, '-'); +- last_b = strrchr (version_b, '-'); +- +- if (last_a != NULL) { +- pkgver_a = g_strndup (version_a, last_a - version_a); +- } else { +- pkgver_a = g_strdup (version_a); +- } +- +- if (last_b != NULL) { +- pkgver_b = g_strndup (version_b, last_b - version_b); +- } else { +- pkgver_b = g_strdup (version_b); +- } +- +- result = pacman_package_compare_version (pkgver_a, pkgver_b); +- +- g_free (pkgver_a); +- g_free (pkgver_b); +- +- return result; +-} +- +-static gboolean +-backend_get_update_detail_thread (PkBackend *backend) +-{ +- guint iterator; +- +- gchar **package_ids; +- +- g_return_val_if_fail (local_database != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- package_ids = pk_backend_get_strv (backend, "package_ids"); +- +- g_return_val_if_fail (package_ids != NULL, FALSE); +- +- /* collect details about updates */ +- for (iterator = 0; package_ids[iterator] != NULL; ++iterator) { +- PacmanPackage *package, *upgrades; +- PacmanDatabase *database; +- +- gchar *upgrades_id, *replaces_ids, *vendor_url; +- const gchar *message; +- +- PkRestartEnum restart; +- PkUpdateStateEnum state; +- +- GTimeVal built = { 0 }, installed = { 0 }; +- gchar *issued, *updated; +- +- if (backend_cancelled (backend)) { +- break; +- } +- +- package = backend_get_package (backend, package_ids[iterator]); +- if (package == NULL) { +- backend_finished (backend); +- return FALSE; +- } +- +- upgrades = pacman_database_find_package (local_database, pacman_package_get_name (package)); +- if (upgrades != NULL) { +- upgrades_id = pacman_package_make_id (upgrades); +- if (pacman_package_compare_pkgver (package, upgrades) != 0) { +- message = "Update to newest upstream version"; +- } else { +- message = "Update to newest release"; +- } +- } else { +- upgrades_id = NULL; +- message = "Install as a replacement for an older package"; +- } +- +- database = pacman_package_get_database (package); +- replaces_ids = pacman_package_make_replaces_ids (package); +- vendor_url = pacman_package_make_vendor_url (package); +- +- if (g_str_has_prefix (pacman_package_get_name (package), "kernel")) { +- restart = PK_RESTART_ENUM_SYSTEM; +- } else { +- restart = PK_RESTART_ENUM_NONE; +- } +- +- if (g_str_has_suffix (pacman_database_get_name (database), "testing")) { +- state = PK_UPDATE_STATE_ENUM_TESTING; +- } else { +- state = PK_UPDATE_STATE_ENUM_STABLE; +- } +- +- built.tv_sec = pacman_package_get_build_date (package); +- if (built.tv_sec > 0) { +- issued = g_time_val_to_iso8601 (&built); +- } else { +- issued = NULL; +- } +- +- if (upgrades != NULL) { +- installed.tv_sec = pacman_package_get_install_date (upgrades); +- if (installed.tv_sec > 0) { +- updated = g_time_val_to_iso8601 (&installed); +- } else { +- updated = NULL; +- } +- } else { +- updated = NULL; +- } +- +- pk_backend_update_detail (backend, package_ids[iterator], upgrades_id, replaces_ids, vendor_url, NULL, NULL, restart, message, NULL, state, issued, updated); +- +- g_free (issued); +- g_free (updated); +- +- g_free (vendor_url); +- g_free (replaces_ids); +- g_free (upgrades_id); +- } +- +- backend_finished (backend); +- return TRUE; +-} +- +-/** +- * backend_get_update_detail: +- **/ +-void +-backend_get_update_detail (PkBackend *backend, gchar **package_ids) +-{ +- g_return_if_fail (backend != NULL); +- g_return_if_fail (package_ids != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_get_update_detail_thread); +-} +- +-static gboolean +-pacman_package_should_ignore (PacmanPackage *package) +-{ +- const PacmanList *groups; +- const PacmanList *ignore_packages; +- const PacmanList *ignore_groups; +- +- g_return_val_if_fail (pacman != NULL, TRUE); +- g_return_val_if_fail (package != NULL, TRUE); +- +- ignore_packages = pacman_manager_get_ignore_packages (pacman); +- +- /* check if package is an IgnorePkg */ +- if (pacman_list_find_string (ignore_packages, pacman_package_get_name (package)) != NULL) { +- return TRUE; +- } +- +- ignore_groups = pacman_manager_get_ignore_groups (pacman); +- +- /* check if package is in an IgnoreGroup */ +- for (groups = pacman_package_get_groups (package); groups != NULL; groups = pacman_list_next (groups)) { +- if (pacman_list_find_string (ignore_groups, (const gchar *) pacman_list_get (groups)) != NULL) { +- return TRUE; +- } +- } +- +- return FALSE; +-} +- +-static gboolean +-pacman_package_should_sync_first (PacmanPackage *package) +-{ +- const PacmanList *sync_firsts; +- +- g_return_val_if_fail (pacman != NULL, FALSE); +- g_return_val_if_fail (package != NULL, FALSE); +- +- sync_firsts = pacman_manager_get_sync_firsts (pacman); +- +- /* check if package is in SyncFirst */ +- if (pacman_list_find_string (sync_firsts, pacman_package_get_name (package)) != NULL) { +- return TRUE; +- } +- +- return FALSE; +-} +- +-static gboolean +-backend_get_updates_thread (PkBackend *backend) +-{ +- struct stat cache; +- time_t one_hour_ago; +- +- PacmanTransaction *transaction = NULL; +- PacmanTransactionFlags flags = PACMAN_TRANSACTION_FLAGS_NONE; +- +- const PacmanList *packages; +- +- g_return_val_if_fail (local_database != NULL, FALSE); +- g_return_val_if_fail (pacman != NULL, FALSE); +- g_return_val_if_fail (backend != NULL, FALSE); +- +- time (&one_hour_ago); +- one_hour_ago -= 60 * 60; +- +- /* refresh databases if they are older than an hour */ +- if (g_stat (PACMAN_CACHE_PATH, &cache) < 0 || cache.st_mtime < one_hour_ago) { +- transaction = backend_transaction_run (backend, PACMAN_TRANSACTION_UPDATE, flags, NULL); +- +- if (transaction != NULL) { +- g_object_unref (transaction); +- } else { +- backend_finished (backend); +- return FALSE; +- } +- } else { +- g_debug ("pacman: databases have been refreshed recently"); +- } +- +- /* find outdated and replacement packages */ +- for (packages = pacman_database_get_packages (local_database); packages != NULL; packages = pacman_list_next (packages)) { +- PacmanPackage *package = (PacmanPackage *) pacman_list_get (packages); +- PacmanPackage *upgrade = pacman_package_find_upgrade (package, pacman_manager_get_sync_databases (pacman)); +- +- if (backend_cancelled (backend)) { +- break; +- } +- +- if (upgrade != NULL) { +- PkInfoEnum info; +- +- if (pacman_package_should_ignore (upgrade)) { +- info = PK_INFO_ENUM_BLOCKED; +- } else if (pacman_package_should_sync_first (upgrade)) { +- info = PK_INFO_ENUM_IMPORTANT; +- } else { +- info = PK_INFO_ENUM_NORMAL; +- } +- +- backend_package (backend, upgrade, info); +- } +- } +- +- backend_finished (backend); +- return TRUE; +-} +- +-/** +- * backend_get_updates: +- **/ +-void +-backend_get_updates (PkBackend *backend, PkBitfield filters) +-{ +- g_return_if_fail (backend != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_QUERY, backend_get_updates_thread); +-} +- +-static gboolean +-backend_refresh_cache_thread (PkBackend *backend) +-{ +- gboolean force; +- +- PacmanTransaction *transaction = NULL; +- PacmanTransactionFlags flags = PACMAN_TRANSACTION_FLAGS_NONE; +- +- g_return_val_if_fail (backend != NULL, FALSE); +- +- force = pk_backend_get_bool (backend, "force"); +- +- /* download databases even if they are older than current */ +- if (force) { +- flags |= PACMAN_TRANSACTION_FLAGS_UPDATE_ALLOW_DOWNGRADE; +- } +- +- /* run the transaction */ +- transaction = backend_transaction_run (backend, PACMAN_TRANSACTION_UPDATE, flags, NULL); +- +- return backend_transaction_finished (backend, transaction); +-} +- +-/** +- * backend_refresh_cache: +- **/ +-void +-backend_refresh_cache (PkBackend *backend, gboolean force) +-{ +- g_return_if_fail (backend != NULL); +- +- backend_run (backend, PK_STATUS_ENUM_SETUP, backend_refresh_cache_thread); +-} +diff --git a/backends/pacman/backend-update.h b/backends/pacman/backend-update.h +deleted file mode 100644 +index 2a8bf02..0000000 +--- a/backends/pacman/backend-update.h ++++ /dev/null +@@ -1,31 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2007 Andreas Obergrusberger +- * Copyright (C) 2008, 2009 Valeriy Lyasotskiy +- * Copyright (C) 2010 Jonathan Conder +- * +- * Licensed under the GNU General Public License Version 2 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- */ +- +-#include +- +-void backend_get_update_detail (PkBackend *backend, +- gchar **package_ids); +-void backend_get_updates (PkBackend *backend, +- PkBitfield filters); +-void backend_refresh_cache (PkBackend *backend, +- gboolean force); +diff --git a/backends/pacman/groups.list b/backends/pacman/groups.list +deleted file mode 100644 +index b2c02ae..0000000 +--- a/backends/pacman/groups.list ++++ /dev/null +@@ -1,65 +0,0 @@ +-adesklet-desklets desktop-other +-base system +-base-devel programming +-bmp-io-plugins multimedia +-bmp-plugins multimedia +-cegcc programming +-compiz desktop-other +-compiz-fusion desktop-other +-compiz-fusion-gtk desktop-gnome +-compiz-fusion-kde desktop-kde +-compiz-gnome desktop-gnome +-compiz-gtk desktop-gnome +-compiz-kde desktop-kde +-e17-extra-svn desktop-other +-e17-libs-svn desktop-other +-e17-svn desktop-other +-fprint other +-gimp-help other +-gimp-plugins other +-gnome desktop-gnome +-gnome-extra desktop-gnome +-gnustep-core desktop-other +-google-gadgets desktop-other +-gstreamer0.10-plugins multimedia +-kde desktop-kde +-kdeaccessibility desktop-kde +-kdeadmin desktop-kde +-kdeartwork desktop-kde +-kdebase desktop-kde +-kdeedu desktop-kde +-kde-extragear desktop-kde +-kdegames desktop-kde +-kdegraphics desktop-kde +-kde-l10n desktop-kde +-kde-meta desktop-kde +-kdemultimedia desktop-kde +-kdenetwork desktop-kde +-kdepim desktop-kde +-kdeplasma-addons desktop-kde +-kdesdk desktop-kde +-kdetoys desktop-kde +-kdeutils desktop-kde +-kdewebdev desktop-kde +-koffice desktop-kde +-ladspa-plugins multimedia +-lib32 other +-lxde other +-qtcurve desktop-kde +-rox-desktop desktop-other +-telepathy other +-texlive-lang other +-texlive-lang-doc other +-texlive-most other +-texlive-most-doc other +-thunderbird-i18n other +-thunderbird-spell-i18n other +-vim-plugins other +-xfce4 desktop-xfce +-xfce4-goodies desktop-xfce +-xmms-effect-plugins multimedia +-xmms-io-plugins multimedia +-xmms-plugins multimedia +-xorg desktop-other +-xorg-input-drivers desktop-other +-xorg-video-drivers desktop-other +diff --git a/backends/pacman/pacman.conf b/backends/pacman/pacman.conf +deleted file mode 100644 +index 40b8e4a..0000000 +--- a/backends/pacman/pacman.conf ++++ /dev/null +@@ -1,12 +0,0 @@ +-# PackageKit configuration for the pacman backend +-# See the pacman.conf(5) manpage for option and repository directives. +- +-[options] +- +-# Use default pacman configuration initially +-# +-Include = /etc/pacman.conf +- +-# Prevent PackageKit from removing itself +-# +-HoldPkg = packagekit +diff --git a/configure.ac b/configure.ac +index ad86e3b..6604ac5 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -487,7 +487,6 @@ AC_ARG_ENABLE(conary, AS_HELP_STRING([--enable-conary],[use the CONARY backend]) + AC_ARG_ENABLE(dummy, AS_HELP_STRING([--enable-dummy],[use the dummy backend]),enable_dummy=$enableval,enable_dummy=yes) + AC_ARG_ENABLE(entropy, AS_HELP_STRING([--enable-entropy],[use the entropy backend]),enable_entropy=$enableval,enable_entropy=no) + AC_ARG_ENABLE(opkg, AS_HELP_STRING([--enable-opkg],[use the OPKG backend]),enable_opkg=$enableval,enable_opkg=no) +-AC_ARG_ENABLE(pacman, AS_HELP_STRING([--enable-pacman],[use the Pacman backend]),enable_pacman=$enableval,enable_pacman=no) + AC_ARG_ENABLE(pisi, AS_HELP_STRING([--enable-pisi],[use the PiSi backend]),enable_pisi=$enableval,enable_pisi=no) + AC_ARG_ENABLE(poldek, AS_HELP_STRING([--enable-poldek],[use the poldek backend]),enable_poldek=$enableval,enable_poldek=no) + AC_ARG_ENABLE(portage, AS_HELP_STRING([--enable-portage],[use the portage backend]),enable_portage=$enableval,enable_portage=no) +@@ -509,7 +508,6 @@ AM_CONDITIONAL(BACKEND_TYPE_CONARY, [test x$enable_conary = xyes]) + AM_CONDITIONAL(BACKEND_TYPE_DUMMY, [test x$enable_dummy = xyes]) + AM_CONDITIONAL(BACKEND_TYPE_ENTROPY, [test x$enable_entropy = xyes]) + AM_CONDITIONAL(BACKEND_TYPE_OPKG, [test x$enable_opkg = xyes]) +-AM_CONDITIONAL(BACKEND_TYPE_PACMAN, [test x$enable_pacman = xyes]) + AM_CONDITIONAL(BACKEND_TYPE_PISI, [test x$enable_pisi = xyes]) + AM_CONDITIONAL(BACKEND_TYPE_POLDEK, [test x$enable_poldek = xyes]) + AM_CONDITIONAL(BACKEND_TYPE_PORTAGE, [test x$enable_portage = xyes]) +@@ -610,8 +608,6 @@ if test x$with_default_backend = x; then + with_default_backend=slapt + elif test -f /usr/bin/smart ; then + with_default_backend=smart +- elif test -f /usr/lib/libpacman-glib.so ; then +- with_default_backend=pacman + elif test -f /usr/bin/pisi ; then + with_default_backend=pisi + elif test -f /usr/bin/razor ; then +@@ -710,12 +706,6 @@ if test x$enable_alpm = xyes; then + [AC_MSG_ERROR([No ALPM headers found])]) + fi + +-if test x$enable_pacman = xyes; then +- PKG_CHECK_MODULES(PACMAN, pacman-glib >= 3.3.0) +- AC_SUBST(PACMAN_CFLAGS) +- AC_SUBST(PACMAN_LIBS) +-fi +- + if test x$enable_poldek = xyes; then + POLDEK_CFLAGS="-I/usr/include/poldek" + POLDEK_LIBS="-lpoclidek -lpoldek" +@@ -794,7 +784,6 @@ backends/conary/Makefile + backends/dummy/Makefile + backends/entropy/Makefile + backends/opkg/Makefile +-backends/pacman/Makefile + backends/slapt/Makefile + backends/smart/Makefile + backends/test/Makefile +@@ -870,7 +859,6 @@ echo " + Entropy backend: ${enable_entropy} + OPKG backend: ${enable_opkg} + Razor backend: ${enable_razor} +- Pacman backend: ${enable_pacman} + PiSi backend: ${enable_pisi} + poldek backend: ${enable_poldek} + Portage backend: ${enable_portage} +diff --git a/docs/html/pk-matrix.html b/docs/html/pk-matrix.html +index 33f2efb..91dc2d4 100644 +--- a/docs/html/pk-matrix.html ++++ b/docs/html/pk-matrix.html +@@ -28,7 +28,6 @@ +
conary
+
entropy
+
opkg
+-
pacman
+
pisi
+
poldek
+
portage
+@@ -43,12 +42,11 @@ + Cancel + [yes] + [yes] +-[no] ++[yes] + [no] + [yes] + [yes] + [no] +-[yes] + [yes] + [yes] + [yes] +@@ -68,7 +66,6 @@ + [no] + [yes] + [no] +-[yes] + [no] + [no] + [no] +@@ -88,7 +85,6 @@ + [no] + [yes] + [yes] +-[yes] + [yes] + [yes] + [yes] +@@ -108,7 +104,6 @@ + [yes] + [yes] + [yes] +-[yes] + [yes] + [yes] + [yes] +@@ -128,7 +123,6 @@ + [no] + [yes] + [no] +-[no] + [no] + [no] + [no] +@@ -148,7 +142,6 @@ + [yes] + [yes] + [no] +-[yes] + [yes] + [yes] + [yes] +@@ -168,7 +161,6 @@ + [yes] + [yes] + [no] +-[yes] + [no] + [yes] + [yes] +@@ -188,7 +180,6 @@ + [no] + [yes] + [no] +-[yes] + [yes] + [yes] + [yes] +@@ -203,12 +194,11 @@ + GetRequires + [yes] + [yes] +-[no] ++[yes] + [yes] + [yes] + [yes] + [no] +-[yes] + [yes] + [yes] + [yes] +@@ -228,7 +218,6 @@ + [yes] + [yes] + [no] +-[yes] + [no] + [yes] + [yes] +@@ -248,7 +237,6 @@ + [yes] + [yes] + [yes] +-[yes] + [yes] + [yes] + [yes] +@@ -268,7 +256,6 @@ + [no] + [yes] + [no] +-[yes] + [yes] + [no] + [no] +@@ -288,7 +275,6 @@ + [yes] + [yes] + [yes] +-[yes] + [yes] + [yes] + [yes] +@@ -308,7 +294,6 @@ + [no] + [no] + [no] +-[no] + [no] + [no] + [no] +@@ -328,7 +313,6 @@ + [yes] + [yes] + [yes] +-[yes] + [yes] + [yes] + [yes] +@@ -348,7 +332,6 @@ + [yes] + [yes] + [yes] +-[yes] + [yes] + [yes] + [yes] +@@ -363,12 +346,11 @@ + RepoEnable + [yes] + [yes] +-[no] ++[yes] + [yes] + [no] + [yes] + [no] +-[yes] + [no] + [no] + [yes] +@@ -388,7 +370,6 @@ + [no] + [no] + [no] +-[no] + [yes] + [no] + [no] +@@ -408,7 +389,6 @@ + [yes] + [yes] + [no] +-[yes] + [yes] + [yes] + [yes] +@@ -428,7 +408,6 @@ + [no] + [no] + [no] +-[no] + [no] + [no] + [no] +@@ -448,7 +427,6 @@ + [yes] + [yes] + [yes] +-[yes] + [yes] + [yes] + [yes] +@@ -463,12 +441,11 @@ + SearchFile + [yes] + [yes] +-[no] ++[yes] + [yes] + [no] + [yes] + [no] +-[yes] + [yes] + [yes] + [yes] +@@ -488,7 +465,6 @@ + [yes] + [yes] + [yes] +-[yes] + [yes] + [yes] + [yes] +@@ -508,7 +484,6 @@ + [yes] + [yes] + [yes] +-[yes] + [yes] + [yes] + [yes] +@@ -523,12 +498,11 @@ + SimulateInstallFiles + [yes] + [no] +-[no] ++[yes] + [no] + [no] + [yes] + [no] +-[no] + [no] + [no] + [no] +@@ -543,12 +517,11 @@ + SimulateInstallPackages + [yes] + [yes] +-[no] ++[yes] + [no] + [no] + [yes] + [no] +-[yes] + [no] + [yes] + [no] +@@ -563,12 +536,11 @@ + SimulateRemovePackages + [yes] + [yes] +-[no] ++[yes] + [no] + [no] + [yes] + [no] +-[yes] + [no] + [yes] + [no] +@@ -583,12 +555,11 @@ + SimulateUpdatePackages + [yes] + [yes] +-[no] ++[yes] + [no] + [no] + [yes] + [no] +-[yes] + [no] + [yes] + [no] +@@ -608,7 +579,6 @@ + [yes] + [yes] + [yes] +-[yes] + [yes] + [yes] + [yes] +@@ -628,7 +598,6 @@ + [yes] + [yes] + [yes] +-[no] + [yes] + [yes] + [yes] +@@ -648,7 +617,6 @@ + [no] + [yes] + [no] +-[yes] + [no] + [yes] + [no] +@@ -672,7 +640,6 @@ +
conary
+
entropy
+
opkg
+-
pacman
+
pisi
+
poldek
+
portage
+@@ -692,7 +659,6 @@ + [yes] + [yes] + [yes] +-[yes] + [yes] + [yes] + [yes] +@@ -712,7 +678,6 @@ + [no] + [yes] + [yes] +-[no] + [yes] + [yes] + [no] +@@ -732,7 +697,6 @@ + [no] + [yes] + [yes] +-[no] + [yes] + [yes] + [no] +@@ -752,7 +716,6 @@ + [no] + [yes] + [no] +-[no] + [no] + [no] + [yes] +@@ -772,7 +735,6 @@ + [no] + [no] + [no] +-[no] + [no] + [no] + [no] +@@ -792,7 +754,6 @@ + [no] + [no] + [no] +-[no] + [no] + [no] + [no] +@@ -812,7 +773,6 @@ + [no] + [no] + [no] +-[no] + [no] + [yes] + [yes] +@@ -832,7 +792,6 @@ + [no] + [no] + [no] +-[no] + [no] + [no] + [no] +@@ -852,7 +811,6 @@ + [no] + [no] + [no] +-[no] + [no] + [no] + [no] diff --git a/community/packagekit/packagekit.install b/community/packagekit/packagekit.install new file mode 100644 index 000000000..7c8a8bd2b --- /dev/null +++ b/community/packagekit/packagekit.install @@ -0,0 +1,11 @@ +post_install() { + update-mime-database usr/share/mime &> /dev/null +} + +post_upgrade() { + post_install +} + +post_remove() { + post_install +} -- cgit v1.2.3-54-g00ecf