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]