summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDetlev Casanova <detlev.casanova@gmail.com>2010-07-09 12:58:49 +0200
committerDetlev Casanova <detlev.casanova@gmail.com>2010-07-09 12:58:49 +0200
commit69567b830f119ff74706bbdb6f58164201890623 (patch)
treec867abe317220d091a8f280ee4345ca8d2b86529
parent4e75e7f79601122313e83c4e8d22492492e970e2 (diff)
downloadlayman-69567b830f119ff74706bbdb6f58164201890623.tar.gz
layman-69567b830f119ff74706bbdb6f58164201890623.tar.bz2
layman-69567b830f119ff74706bbdb6f58164201890623.zip
Remove the runner
Implement _eq_ and setPriority
-rw-r--r--src/overlay.c17
-rw-r--r--src/overlay.h10
-rwxr-xr-xsrc/pkBackend.py1889
-rw-r--r--src/runner.c132
-rw-r--r--src/runner.h6
-rwxr-xr-xsrc/test.py15
6 files changed, 23 insertions, 2046 deletions
diff --git a/src/overlay.c b/src/overlay.c
index 74910f9..9b2b2f7 100644
--- a/src/overlay.c
+++ b/src/overlay.c
@@ -142,6 +142,23 @@ const char *overlayToXml(Overlay *o)
return PyBytes_AsString(str);
}
+void overlaySetPriority(Overlay *o, int priority)
+{
+ if (!o || !o->object)
+ return;
+
+ PyObject_CallMethod(o->object, "set_priority", "(I)", priority);
+}
+
+int overlaySame(Overlay *o1, Overlay *o2)
+{
+ PyObject *ret = PyObject_RichCompare(o1->object, o2->object, Py_EQ);
+ if (!ret)
+ return 0;
+
+ return PyObject_IsTrue(ret);
+}
+
void overlayFree(Overlay *o)
{
if (o && o->object)
diff --git a/src/overlay.h b/src/overlay.h
index 2f64bde..d6b96fd 100644
--- a/src/overlay.h
+++ b/src/overlay.h
@@ -1,18 +1,20 @@
#ifndef OVERLAY_H
#define OVERLAY_H
+//TODO:document me !
+
typedef struct Overlay Overlay;
Overlay* createOverlay(const char*, const char*, int, int);
const char* overlayName(Overlay*);
const char* overlayOwnerEmail(Overlay*);
const char* overlayDescription(Overlay*);
-const char* overlayShortList(Overlay *o);
-const char* overlayStr(Overlay *o);
-const char* overlayToXml(Overlay *o);
+const char* overlayShortList(Overlay*);
+const char* overlayStr(Overlay*);
+const char* overlayToXml(Overlay*);
int overlayPriority(Overlay*);
int overlayIsOfficial(Overlay*);
-int overlayIsSupported(Overlay *o);
+int overlayIsSupported(Overlay*);
void overlayFree(Overlay*);
#endif
diff --git a/src/pkBackend.py b/src/pkBackend.py
deleted file mode 100755
index 3ec1d2d..0000000
--- a/src/pkBackend.py
+++ /dev/null
@@ -1,1889 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# vim:set shiftwidth=4 tabstop=4 expandtab:
-#
-# Copyright (C) 2009 Mounir Lamouri (volkmar) <mounir.lamouri@gmail.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed 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.
-
-# packagekit imports
-from packagekit.backend import *
-from packagekit.progress import *
-from packagekit.package import PackagekitPackage
-
-# portage imports
-import portage
-import portage.versions
-import portage.dep
-import _emerge.actions
-import _emerge.stdout_spinner
-import _emerge.create_depgraph_params
-import _emerge.AtomArg
-
-# layman imports
-import layman.db
-import layman.config
-
-# misc imports
-import sys
-import signal
-import re
-from itertools import izip
-
-# NOTES:
-#
-# Package IDs description:
-# CAT/PN;PV;KEYWORD;[REPOSITORY|installed]
-# Last field must be "installed" if installed. Otherwise it's the repo name
-#
-# Naming convention:
-# cpv: category package version, the standard representation of what packagekit
-# names a package (an ebuild for portage)
-
-# TODO:
-# remove percentage(None) if percentage is used
-# protection against signal when installing/removing
-
-# Map Gentoo categories to the PackageKit group name space
-class PortagePackageGroups(dict):
- """
- Portage Package categories group representation
- """
- def __init__(self):
- dict.__init__(self)
-
- data = {
- 'accessibility': {
- 'name': "Accessibility",
- 'description': "Accessibility applications",
- 'categories': ['app-accessibility'],
- },
- 'office': {
- 'name': "Office",
- 'description': "Applications used in office environments",
- 'categories': ['app-office', 'app-pda', 'app-mobilephone',
- 'app-cdr', 'app-antivirus', 'app-laptop', 'mail-',
- ],
- },
- 'development': {
- 'name': "Development",
- 'description': "Applications or system libraries",
- 'categories': ['dev-', 'sys-devel'],
- },
- 'system': {
- 'name': "System",
- 'description': "System applications or libraries",
- 'categories': ['sys-'],
- },
- 'games': {
- 'name': "Games",
- 'description': "Games, enjoy your spare time",
- 'categories': ['games-'],
- },
- 'gnome': {
- 'name': "GNOME Desktop",
- 'description': \
- "Applications and libraries for the GNOME Desktop",
- 'categories': ['gnome-'],
- },
- 'kde': {
- 'name': "KDE Desktop",
- 'description': \
- "Applications and libraries for the KDE Desktop",
- 'categories': ['kde-'],
- },
- 'xfce': {
- 'name': "XFCE Desktop",
- 'description': \
- "Applications and libraries for the XFCE Desktop",
- 'categories': ['xfce-'],
- },
- 'lxde': {
- 'name': "LXDE Desktop",
- 'description': \
- "Applications and libraries for the LXDE Desktop",
- 'categories': ['lxde-'],
- },
- 'multimedia': {
- 'name': "Multimedia",
- 'description': \
- "Applications and libraries for Multimedia",
- 'categories': ['media-'],
- },
- 'networking': {
- 'name': "Networking",
- 'description': \
- "Applications and libraries for Networking",
- 'categories': ['net-', 'www-'],
- },
- 'science': {
- 'name': "Science",
- 'description': \
- "Scientific applications and libraries",
- 'categories': ['sci-'],
- },
- 'security': {
- 'name': "Security",
- 'description': \
- "Security orientend applications",
- 'categories': ['app-antivirus', 'net-analyzer', 'net-firewall'],
- },
- 'x11': {
- 'name': "X11",
- 'description': \
- "Applications and libraries for X11",
- 'categories': ['x11-'],
- },
- }
-
- self.update(data)
-
-
-class PortageBridge():
- '''
- Bridge to portage/emerge settings and variabales to help using them
- and be sure they are always up-to-date.
- '''
-
- def __init__(self):
- self.settings = None
- self.trees = None
- self.mtimedb = None
- self.vardb = None
- self.portdb = None
- self.root_config = None
-
- self.update()
-
- def update(self):
- self.settings, self.trees, self.mtimedb = \
- _emerge.actions.load_emerge_config()
- self.vardb = self.trees[self.settings['ROOT']]['vartree'].dbapi
- self.portdb = self.trees[self.settings['ROOT']]['porttree'].dbapi
- self.root_config = self.trees[self.settings['ROOT']]['root_config']
-
- # doing all the changes to settings
- self.settings.unlock()
-
- # we don't want interactive ebuilds
- self.settings["ACCEPT_PROPERTIES"] = "-interactive"
- self.settings.backup_changes("ACCEPT_PROPERTIES")
-
- # do not log with mod_echo (cleanly prevent some outputs)
- def filter_echo(x): return x != 'echo'
- elogs = self.settings["PORTAGE_ELOG_SYSTEM"].split()
- elogs = filter(filter_echo, elogs)
- self.settings["PORTAGE_ELOG_SYSTEM"] = ' '.join(elogs)
- self.settings.backup_changes("PORTAGE_ELOG_SYSTEM")
-
- # finally, regenerate settings and lock them again
- self.settings.regenerate()
- self.settings.lock()
-
-
-class PackageKitPortageMixin(object):
-
- def __init__(self):
- object.__init__(self)
-
- self.pvar = PortageBridge()
- # TODO: should be removed when using non-verbose function API
- # FIXME: avoid using /dev/null, dangerous (ro fs)
- self._dev_null = open('/dev/null', 'w')
- # TODO: atm, this stack keep tracks of elog messages
- self._elog_messages = []
- self._error_message = ""
- self._error_phase = ""
-
- # TODO: should be removed when using non-verbose function API
- def _block_output(self):
- sys.stdout = self._dev_null
- sys.stderr = self._dev_null
-
- # TODO: should be removed when using non-verbose function API
- def _unblock_output(self):
- sys.stdout = sys.__stdout__
- sys.stderr = sys.__stderr__
-
- def _is_repo_enabled(self, layman_db, repo_name):
- if repo_name in layman_db.overlays.keys():
- return True
- return False
-
- def _get_search_list(self, keys_list):
- '''
- Get a string composed of keys (separated with spaces).
- Returns a list of compiled regular expressions.
- '''
- search_list = []
-
- for k in keys_list:
- # not done entirely by pk-transaction
- k = re.escape(k)
- search_list.append(re.compile(k, re.IGNORECASE))
-
- return search_list
-
- def _get_portage_categories(self):
- """
- Return a list of available Portage categories
- """
- return self.pvar.settings.categories
-
- def _get_portage_category_description(self, category):
-
- from xml.dom import minidom
- data = {}
- portdir = self.pvar.settings['PORTDIR']
- myfile = os.path.join(portdir, category, "metadata.xml")
- if os.access(myfile, os.R_OK) and os.path.isfile(myfile):
- doc = minidom.parse(myfile)
- longdescs = doc.getElementsByTagName("longdescription")
- for longdesc in longdescs:
- data[longdesc.getAttribute("lang").strip()] = \
- ' '.join([x.strip() for x in \
- longdesc.firstChild.data.strip().split("\n")])
-
- # Only return in plain English since Portage doesn't support i18n/l10n
- return data.get('en', "No description")
-
- def _get_portage_groups(self):
- """
- Return an expanded version of PortagePackageGroups
- """
- groups = PortagePackageGroups()
- categories = self._get_portage_categories()
-
- # expand categories
- for data in list(groups.values()):
-
- exp_cats = set()
- for g_cat in data['categories']:
- exp_cats.update([x for x in categories if x.startswith(g_cat)])
- data['categories'] = sorted(exp_cats)
-
- return groups
-
- def _get_pk_group(self, cp):
- """
- Return PackageKit group belonging to given Portage package.
- """
- category = portage.versions.catsplit(cp)[0]
- group_data = [key for key, data in self._get_portage_groups().items() \
- if category in data['categories']]
- try:
- generic_group_name = group_data.pop(0)
- except IndexError:
- return GROUP_UNKNOWN
-
- return PackageKitPortageBackend.GROUP_MAP[generic_group_name]
-
- def _get_portage_group(self, pk_group):
- """
- Given a PackageKit group identifier, return Portage packages group.
- """
- group_map = PackageKitPortageBackend.GROUP_MAP
- # reverse dict
- group_map_reverse = dict((y, x) for x, y in group_map.items())
- return group_map_reverse.get(pk_group, 'unknown')
-
- def _get_ebuild_settings(self, cpv, metadata):
- """
- Return values of given metadata keys for given Portage CPV.
- """
- settings = portage.config(clone=self.pvar.settings)
- settings.setcpv(cpv, mydb=metadata)
- return settings
-
- def _is_installed(self, cpv):
- if self.pvar.vardb.cpv_exists(cpv):
- return True
- return False
-
- def _is_cpv_valid(self, cpv):
- if self._is_installed(cpv):
- # actually if is_installed return True that means cpv is in db
- return True
- elif self.pvar.portdb.cpv_exists(cpv):
- return True
-
- return False
-
- def _get_real_license_str(self, cpv, metadata):
- # use conditionals info (w/ USE) in LICENSE and remove ||
- ebuild_settings = self._get_ebuild_settings(cpv, metadata)
- license = set(portage.flatten(portage.dep.use_reduce(
- portage.dep.paren_reduce(metadata["LICENSE"]),
- uselist=ebuild_settings.get("USE", "").split())))
- license.discard('||')
- license = ' '.join(license)
-
- return license
-
- def _signal_config_update(self):
- result = list(portage.util.find_updated_config_files(
- self.pvar.settings['ROOT'],
- self.pvar.settings.get('CONFIG_PROTECT', '').split()))
-
- if result:
- message = "Some configuration files need updating."
- message += ";You should use Gentoo's tools to update them (dispatch-conf)"
- message += ";If you can't do that, ask your system administrator."
- self.message(MESSAGE_CONFIG_FILES_CHANGED, message)
-
- def _get_restricted_fetch_files(self, cpv, metadata):
- '''
- This function checks files in SRC_URI and look if they are in DESTDIR.
- Missing files are returned. If there is no issue, None is returned.
- We don't care about digest but only about existance of files.
-
- NOTES:
- - we are assuming the package has RESTRICT='fetch'
- be sure to call this function only in this case.
- - we are not using fetch_check because it's not returning missing files
- so this function is a simplist fetch_check
- '''
- missing_files = []
- ebuild_settings = self._get_ebuild_settings(cpv, metadata)
-
- files = self.pvar.portdb.getFetchMap(cpv,
- ebuild_settings['USE'].split())
-
- for f in files:
- file_path = os.path.join(ebuild_settings["DISTDIR"], f)
- if not os.access(file_path, os.F_OK):
- missing_files.append([file_path, files[f]])
-
- if len(missing_files) > 0:
- return missing_files
-
- return None
-
- def _check_fetch_restrict(self, packages_list):
- for p in packages_list:
- if 'fetch' in p.metadata['RESTRICT']:
- files = self._get_restricted_fetch_files(p.cpv, p.metadata)
- if files:
- message = "Package %s can't download some files." % p.cpv
- message += ";Please, download manually the followonig file(s):"
- for x in files:
- message += ";- %s then copy it to %s" % (' '.join(x[1]), x[0])
- self.error(ERROR_RESTRICTED_DOWNLOAD, message)
-
- def _elog_listener(self, settings, key, logentries, fulltext):
- '''
- This is a listener for elog.
- It's called each time elog is emitting log messages (at end of process).
- We are not using settings and fulltext but they are used by other
- listeners so we have to keep them as arguments.
- '''
- message = "Messages for package %s:;" % str(key)
- error_message = ""
-
- # building the message
- for phase in logentries:
- for entries in logentries[phase]:
- type = entries[0]
- messages = entries[1]
-
- # TODO: portage.elog.filtering is using upper() should we ?
- if type == 'LOG':
- message += ";Information messages:"
- elif type == 'WARN':
- message += ";Warning messages:"
- elif type == 'QA':
- message += ";QA messages:"
- elif type == 'ERROR':
- message += ";Error messages:"
- self._error_phase = phase
- else:
- continue
-
- for msg in messages:
- msg = msg.replace('\n', '')
- if type == 'ERROR':
- error_message += msg + ";"
- message += "; " + msg
-
- # add the message to the stack
- self._elog_messages.append(message)
- self._error_message = message
-
- def _send_merge_error(self, default):
- # EAPI-2 compliant (at least)
- # 'other' phase is ignored except this one, every phase should be there
- if self._error_phase in ("setup", "unpack", "prepare", "configure",
- "nofetch", "config", "info"):
- error_type = ERROR_PACKAGE_FAILED_TO_CONFIGURE
- elif self._error_phase in ("compile", "test"):
- error_type = ERROR_PACKAGE_FAILED_TO_BUILD
- elif self._error_phase in ("install", "preinst", "postinst",
- "package"):
- error_type = ERROR_PACKAGE_FAILED_TO_INSTALL
- elif self._error_phase in ("prerm", "postrm"):
- error_type = ERROR_PACKAGE_FAILED_TO_REMOVE
- else:
- error_type = default
-
- self.error(error_type, self._error_message)
-
- def _get_file_list(self, cpv):
- cat, pv = portage.versions.catsplit(cpv)
- db = portage.dblink(cat, pv, self.pvar.settings['ROOT'],
- self.pvar.settings, treetype="vartree",
- vartree=self.pvar.vardb)
-
- contents = db.getcontents()
- if not contents:
- return []
-
- return db.getcontents().keys()
-
- def _cmp_cpv(self, cpv1, cpv2):
- '''
- returns 1 if cpv1 > cpv2
- returns 0 if cpv1 = cpv2
- returns -1 if cpv1 < cpv2
- '''
- return portage.versions.pkgcmp(portage.versions.pkgsplit(cpv1),
- portage.versions.pkgsplit(cpv2))
-
- def _get_newest_cpv(self, cpv_list, installed):
- newer = ""
-
- # get the first cpv following the installed rule
- for cpv in cpv_list:
- if self._is_installed(cpv) == installed:
- newer = cpv
- break
-
- if newer == "":
- return ""
-
- for cpv in cpv_list:
- if self._is_installed(cpv) == installed:
- if self._cmp_cpv(cpv, newer) == 1:
- newer = cpv
-
- return newer
-
- def _get_metadata(self, cpv, keys, in_dict = False, add_cache_keys = False):
- '''
- This function returns required metadata.
- If in_dict is True, metadata is returned in a dict object.
- If add_cache_keys is True, cached keys are added to keys in parameter.
- '''
- if self._is_installed(cpv):
- aux_get = self.pvar.vardb.aux_get
- if add_cache_keys:
- keys.extend(list(self.pvar.vardb._aux_cache_keys))
- else:
- aux_get = self.pvar.portdb.aux_get
- if add_cache_keys:
- keys.extend(list(self.pvar.portdb._aux_cache_keys))
-
- if in_dict:
- return dict(izip(keys, aux_get(cpv, keys)))
- else:
- return aux_get(cpv, keys)
-
- def _get_size(self, cpv):
- '''
- Returns the installed size if the package is installed.
- Otherwise, the size of files needed to be downloaded.
- If some required files have been downloaded,
- only the remaining size will be considered.
- '''
- size = 0
- if self._is_installed(cpv):
- size = self._get_metadata(cpv, ["SIZE"])[0]
- if size == '':
- size = 0
- else:
- size = int(size)
- else:
- self
- metadata = self._get_metadata(cpv, ["IUSE", "SLOT"], in_dict=True)
-
- package = _emerge.Package.Package(
- type_name="ebuild",
- built=False,
- installed=False,
- root_config=self.pvar.root_config,
- cpv=cpv,
- metadata=metadata)
-
- fetch_file = self.pvar.portdb.getfetchsizes(package[2],
- package.use.enabled)
- for f in fetch_file:
- size += fetch_file[f]
-
- return size
-
- def _get_cpv_slotted(self, cpv_list):
- cpv_dict = {}
-
- for cpv in cpv_list:
- slot = self._get_metadata(cpv, ["SLOT"])[0]
- if slot not in cpv_dict:
- cpv_dict[slot] = [cpv]
- else:
- cpv_dict[slot].append(cpv)
-
- return cpv_dict
-
- def _filter_free(self, cpv_list, fltlist):
- if not cpv_list:
- return cpv_list
-
- def _has_validLicense(cpv):
- metadata = self._get_metadata(cpv, ["LICENSE", "USE", "SLOT"], True)
- return not self.pvar.settings._getMissingLicenses(cpv, metadata)
-
- if FILTER_FREE in fltlist or FILTER_NOT_FREE in fltlist:
- free_licenses = "@FSF-APPROVED"
- if FILTER_FREE in fltlist:
- licenses = "-* " + free_licenses
- elif FILTER_NOT_FREE in fltlist:
- licenses = "* -" + free_licenses
- backup_license = self.pvar.settings["ACCEPT_LICENSE"]
-
- self.pvar.settings.unlock()
- self.pvar.settings["ACCEPT_LICENSE"] = licenses
- self.pvar.settings.backup_changes("ACCEPT_LICENSE")
- self.pvar.settings.regenerate()
-
- cpv_list = filter(_has_validLicense, cpv_list)
-
- self.pvar.settings["ACCEPT_LICENSE"] = backup_license
- self.pvar.settings.backup_changes("ACCEPT_LICENSE")
- self.pvar.settings.regenerate()
- self.pvar.settings.lock()
-
- return cpv_list
-
- def _filter_newest(self, cpv_list, fltlist):
- if len(cpv_list) == 0:
- return cpv_list
-
- if FILTER_NEWEST not in fltlist:
- return cpv_list
-
- if FILTER_INSTALLED in fltlist:
- # we have one package per slot, so it's the newest
- return cpv_list
-
- cpv_dict = self._get_cpv_slotted(cpv_list)
-
- # slots are sorted (dict), revert them to have newest slots first
- slots = cpv_dict.keys()
- slots.reverse()
-
- # empty cpv_list, cpv are now in cpv_dict and cpv_list gonna be repop
- cpv_list = []
-
- for k in slots:
- # if not_intalled on, no need to check for newest installed
- if FILTER_NOT_INSTALLED not in fltlist:
- newest_installed = self._get_newest_cpv(cpv_dict[k], True)
- if newest_installed != "":
- cpv_list.append(newest_installed)
- newest_available = self._get_newest_cpv(cpv_dict[k], False)
- if newest_available != "":
- cpv_list.append(newest_available)
-
- return cpv_list
-
- def _get_all_cp(self, fltlist):
- # NOTES:
- # returns a list of cp
- #
- # FILTERS:
- # - installed: ok
- # - free: ok (should be done with cpv)
- # - newest: ok (should be finished with cpv)
- cp_list = []
-
- if FILTER_INSTALLED in fltlist:
- cp_list = self.pvar.vardb.cp_all()
- elif FILTER_NOT_INSTALLED in fltlist:
- cp_list = self.pvar.portdb.cp_all()
- else:
- # need installed packages first
- cp_list = self.pvar.vardb.cp_all()
- for cp in self.pvar.portdb.cp_all():
- if cp not in cp_list:
- cp_list.append(cp)
-
- return cp_list
-
- def _get_all_cpv(self, cp, fltlist, filter_newest=True):
- # NOTES:
- # returns a list of cpv
- #
- # FILTERS:
- # - installed: ok
- # - free: ok
- # - newest: ok
-
- cpv_list = []
-
- # populate cpv_list taking care of installed filter
- if FILTER_INSTALLED in fltlist:
- cpv_list = self.pvar.vardb.match(cp)
- elif FILTER_NOT_INSTALLED in fltlist:
- for cpv in self.pvar.portdb.match(cp):
- if not self._is_installed(cpv):
- cpv_list.append(cpv)
- else:
- cpv_list = self.pvar.vardb.match(cp)
- for cpv in self.pvar.portdb.match(cp):
- if cpv not in cpv_list:
- cpv_list.append(cpv)
-
- # free filter
- cpv_list = self._filter_free(cpv_list, fltlist)
-
- # newest filter
- if filter_newest:
- cpv_list = self._filter_newest(cpv_list, fltlist)
-
- return cpv_list
-
- def _id_to_cpv(self, pkgid):
- '''
- Transform the package id (packagekit) to a cpv (portage)
- '''
- ret = split_package_id(pkgid)
-
- if len(ret) < 4:
- self.error(ERROR_PACKAGE_ID_INVALID,
- "The package id %s does not contain 4 fields" % pkgid)
- if '/' not in ret[0]:
- self.error(ERROR_PACKAGE_ID_INVALID,
- "The first field of the package id must contain a category")
-
- # remove slot info from version field
- version = ret[1].split(':')[0]
-
- return ret[0] + "-" + version
-
- def _cpv_to_id(self, cpv):
- '''
- Transform the cpv (portage) to a package id (packagekit)
- '''
- package, version, rev = portage.versions.pkgsplit(cpv)
- pkg_keywords, repo, slot = self._get_metadata(cpv,
- ["KEYWORDS", "repository", "SLOT"])
-
- pkg_keywords = pkg_keywords.split()
- sys_keywords = self.pvar.settings["ACCEPT_KEYWORDS"].split()
- keywords = []
-
- for x in sys_keywords:
- if x in pkg_keywords:
- keywords.append(x)
-
- # if no keywords, check in package.keywords
- if not keywords:
- key_dict = self.pvar.settings.pkeywordsdict.get(
- portage.dep.dep_getkey(cpv))
- if key_dict:
- for _, keys in key_dict.iteritems():
- for x in keys:
- keywords.append(x)
-
- if not keywords:
- keywords.append("no keywords")
- self.message(MESSAGE_UNKNOWN,
- "No keywords have been found for %s" % cpv)
-
- # don't want to see -r0
- if rev != "r0":
- version = version + "-" + rev
- # add slot info if slot != 0
- if slot != '0':
- version = version + ':' + slot
-
- # if installed, repo should be 'installed', packagekit rule
- if self._is_installed(cpv):
- repo = "installed"
-
- return get_package_id(package, version, ' '.join(keywords), repo)
-
- def _get_required_packages(self, cpv_input, recursive):
- '''
- Get a list of cpv and recursive parameter.
- Returns the list of packages required for cpv list.
- '''
- packages_list = []
-
- myopts = {}
- myopts["--selective"] = True
- myopts["--deep"] = True
-
- myparams = _emerge.create_depgraph_params.create_depgraph_params(
- myopts, "remove")
- depgraph = _emerge.depgraph.depgraph(self.pvar.settings,
- self.pvar.trees, myopts, myparams, None)
-
- # TODO: atm, using FILTER_INSTALLED because it's quicker
- # and we don't want to manage non-installed packages
- for cp in self._get_all_cp([FILTER_INSTALLED]):
- for cpv in self._get_all_cpv(cp, [FILTER_INSTALLED]):
- depgraph._dynamic_config._dep_stack.append(
- _emerge.Dependency.Dependency(
- atom=portage.dep.Atom('=' + cpv),
- root=self.pvar.settings["ROOT"], parent=None))
-
- if not depgraph._complete_graph():
- self.error(ERROR_INTERNAL_ERROR, "Error when generating depgraph")
- return
-
- def _add_children_to_list(packages_list, node):
- for n in depgraph._dynamic_config.digraph.parent_nodes(node):
- if n not in packages_list \
- and not isinstance(n, _emerge.SetArg.SetArg):
- packages_list.append(n)
- _add_children_to_list(packages_list, n)
-
- for node in depgraph._dynamic_config.digraph.__iter__():
- if isinstance(node, _emerge.SetArg.SetArg):
- continue
- if node.cpv in cpv_input:
- if recursive:
- _add_children_to_list(packages_list, node)
- else:
- for n in \
- depgraph._dynamic_config.digraph.parent_nodes(node):
- if not isinstance(n, _emerge.SetArg.SetArg):
- packages_list.append(n)
-
- # remove cpv_input that may be added to the list
- def filter_cpv_input(x): return x.cpv not in cpv_input
- return filter(filter_cpv_input, packages_list)
-
-
-class PackageKitPortageBackend(PackageKitPortageMixin, PackageKitPortageBase):
-
- # Portage <-> PackageKit groups map
- GROUP_MAP = {
- 'accessibility': GROUP_ACCESSIBILITY,
- 'development': GROUP_PROGRAMMING,
- 'games': GROUP_GAMES,
- 'gnome': GROUP_DESKTOP_GNOME,
- 'kde': GROUP_DESKTOP_KDE,
- 'lxde': GROUP_DESKTOP_OTHER,
- 'multimedia': GROUP_MULTIMEDIA,
- 'networking': GROUP_NETWORK,
- 'office': GROUP_OFFICE,
- 'science': GROUP_SCIENCE,
- 'system': GROUP_SYSTEM,
- 'security': GROUP_SECURITY,
- 'x11': GROUP_OTHER,
- 'xfce': GROUP_DESKTOP_XFCE,
- 'unknown': GROUP_UNKNOWN,
- }
-
- def __sigquit(self, signum, frame):
- raise SystemExit(1)
-
- def __init__(self, args):
- signal.signal(signal.SIGQUIT, self.__sigquit)
- PackageKitPortageMixin.__init__(self)
- PackageKitBaseBackend.__init__(self, args)
-
- def _package(self, cpv, info=None):
- desc = self._get_metadata(cpv, ["DESCRIPTION"])[0]
- if not info:
- if self._is_installed(cpv):
- info = INFO_INSTALLED
- else:
- info = INFO_AVAILABLE
- self.package(self._cpv_to_id(cpv), info, desc)
-
- def get_categories(self):
-
- self.status(STATUS_QUERY)
- self.allow_cancel(True)
-
- categories = self._get_portage_categories()
- if not categories:
- self.error(ERROR_GROUP_LIST_INVALID, "no package categories")
- return
-
- for name in categories:
-
- summary = self._get_portage_category_description(name)
-
- f_name = "/usr/share/pixmaps/portage/%s.png" % (name,)
- if os.path.isfile(f_name) and os.access(f_name, os.R_OK):
- icon = name
- else:
- icon = "image-missing"
-
- cat_id = name # same thing
- self.category("", cat_id, name, summary, icon)
-
- def get_depends(self, filters, pkgs, recursive):
- # TODO: use only myparams ?
- # TODO: improve error management / info
-
- # FILTERS:
- # - installed: ok
- # - free: ok
- # - newest: ignored because only one version of a package is installed
-
- self.status(STATUS_INFO)
- self.allow_cancel(True)
- self.percentage(None)
-
- fltlist = filters.split(';')
-
- cpv_input = []
- cpv_list = []
-
- for pkg in pkgs:
- cpv = self._id_to_cpv(pkg)
- if not self._is_cpv_valid(cpv):
- self.error(ERROR_PACKAGE_NOT_FOUND,
- "Package %s was not found" % pkg)
- continue
- cpv_input.append('=' + cpv)
-
- myopts = {}
- myopts["--selective"] = True
- myopts["--deep"] = True
- myparams = _emerge.create_depgraph_params.create_depgraph_params(
- myopts, "")
-
- depgraph = _emerge.depgraph.depgraph(
- self.pvar.settings, self.pvar.trees, myopts, myparams, None)
- retval, fav = depgraph.select_files(cpv_input)
-
- if not retval:
- self.error(ERROR_DEP_RESOLUTION_FAILED,
- "Wasn't able to get dependency graph")
- return
-
- def _add_children_to_list(cpv_list, node):
- for n in depgraph._dynamic_config.digraph.child_nodes(node):
- if n not in cpv_list:
- cpv_list.append(n)
- _add_children_to_list(cpv_list, n)
-
- for cpv in cpv_input:
- for r in depgraph._dynamic_config.digraph.root_nodes():
- # TODO: remove things with @ as first char
- # TODO: or refuse SetArgs
- if not isinstance(r, _emerge.AtomArg.AtomArg):
- continue
- if r.atom == cpv:
- if recursive:
- _add_children_to_list(cpv_list, r)
- else:
- for n in \
- depgraph._dynamic_config.digraph.child_nodes(r):
- for c in \
- depgraph._dynamic_config.digraph.child_nodes(n):
- cpv_list.append(c)
-
- def _filter_uninstall(cpv):
- return cpv[3] != 'uninstall'
- def _filter_installed(cpv):
- return cpv[0] == 'installed'
- def _filter_not_installed(cpv):
- return cpv[0] != 'installed'
-
- # removing packages going to be uninstalled
- cpv_list = filter(_filter_uninstall, cpv_list)
-
- # install filter
- if FILTER_INSTALLED in fltlist:
- cpv_list = filter(_filter_installed, cpv_list)
- if FILTER_NOT_INSTALLED in fltlist:
- cpv_list = filter(_filter_not_installed, cpv_list)
-
- # now we can change cpv_list to a real cpv list
- tmp_list = cpv_list[:]
- cpv_list = []
- for x in tmp_list:
- cpv_list.append(x[2])
- del tmp_list
-
- # free filter
- cpv_list = self._filter_free(cpv_list, fltlist)
-
- for cpv in cpv_list:
- # prevent showing input packages
- if '=' + cpv not in cpv_input:
- self._package(cpv)
-
- def get_details(self, pkgs):
- self.status(STATUS_INFO)
- self.allow_cancel(True)
- self.percentage(0)
-
- nb_pkg = float(len(pkgs))
- pkg_processed = 0.0
-
- for pkg in pkgs:
- cpv = self._id_to_cpv(pkg)
-
- if not self._is_cpv_valid(cpv):
- self.error(ERROR_PACKAGE_NOT_FOUND,
- "Package %s was not found" % pkg)
- continue
-
- metadata = self._get_metadata(cpv,
- ["DESCRIPTION", "HOMEPAGE", "IUSE", "LICENSE", "SLOT"],
- in_dict=True)
- license = self._get_real_license_str(cpv, metadata)
-
- self.details(self._cpv_to_id(cpv), license,
- self._get_pk_group(cpv),
- metadata["DESCRIPTION"], metadata["HOMEPAGE"],
- self._get_size(cpv))
-
- pkg_processed += 100.0
- self.percentage(int(pkg_processed/nb_pkg))
-
- self.percentage(100)
-
- def get_files(self, pkgs):
- self.status(STATUS_INFO)
- self.allow_cancel(True)
- self.percentage(0)
-
- nb_pkg = float(len(pkgs))
- pkg_processed = 0.0
-
- for pkg in pkgs:
- cpv = self._id_to_cpv(pkg)
-
- if not self._is_cpv_valid(cpv):
- self.error(ERROR_PACKAGE_NOT_FOUND,
- "Package %s was not found" % pkg)
- continue
-
- if not self._is_installed(cpv):
- self.error(ERROR_CANNOT_GET_FILELIST,
- "get-files is only available for installed packages")
- continue
-
- files = self._get_file_list(cpv)
- files = sorted(files)
- files = ";".join(files)
-
- self.files(pkg, files)
-
- pkg_processed += 100.0
- self.percentage(int(pkg_processed/nb_pkg))
-
- self.percentage(100)
-
- def get_packages(self, filters):
- self.status(STATUS_QUERY)
- self.allow_cancel(True)
- self.percentage(0)
-
- fltlist = filters.split(';')
- cp_list = self._get_all_cp(fltlist)
- nb_cp = float(len(cp_list))
- cp_processed = 0.0
-
- for cp in self._get_all_cp(fltlist):
- for cpv in self._get_all_cpv(cp, fltlist):
- self._package(cpv)
-
- cp_processed += 100.0
- self.percentage(int(cp_processed/nb_cp))
-
- self.percentage(100)
-
- def get_repo_list(self, filters):
- # NOTES:
- # use layman API
- # returns only official and supported repositories
- # and creates a dummy repo for portage tree
- self.status(STATUS_INFO)
- self.allow_cancel(True)
- self.percentage(None)
-
- fltlist = filters.split(';')
-
- # get installed and available dbs
- installed_layman_db = layman.db.DB(layman.config.Config())
- available_layman_db = layman.db.RemoteDB(layman.config.Config())
-
- # 'gentoo' is a dummy repo
- self.repo_detail('gentoo', 'Gentoo Portage tree', True)
-
- if FILTER_NOT_DEVELOPMENT not in fltlist:
- for o in available_layman_db.overlays.keys():
- if available_layman_db.overlays[o].is_official() \
- and available_layman_db.overlays[o].is_supported():
- self.repo_detail(o, o,
- self._is_repo_enabled(installed_layman_db, o))
-
- def get_requires(self, filters, pkgs, recursive):
- # TODO: manage non-installed package
-
- # FILTERS:
- # - installed: error atm, see previous TODO
- # - free: ok
- # - newest: ignored because only one version of a package is installed
-
- self.status(STATUS_RUNNING)
- self.allow_cancel(True)
- self.percentage(None)
-
- fltlist = filters.split(';')
-
- cpv_input = []
- cpv_list = []
-
- if FILTER_NOT_INSTALLED in fltlist:
- self.error(ERROR_CANNOT_GET_REQUIRES,
- "get-requires returns only installed packages at the moment")
- return
-
- for pkg in pkgs:
- cpv = self._id_to_cpv(pkg)
-
- if not self._is_cpv_valid(cpv):
- self.error(ERROR_PACKAGE_NOT_FOUND,
- "Package %s was not found" % pkg)
- continue
- if not self._is_installed(cpv):
- self.error(ERROR_CANNOT_GET_REQUIRES,
- "get-requires is only available for installed packages at the moment")
- continue
-
- cpv_input.append(cpv)
-
- packages_list = self._get_required_packages(cpv_input, recursive)
-
- # now we can populate cpv_list
- cpv_list = []
- for p in packages_list:
- cpv_list.append(p.cpv)
- del packages_list
-
- # free filter
- cpv_list = self._filter_free(cpv_list, fltlist)
-
- for cpv in cpv_list:
- # prevent showing input packages
- if '=' + cpv not in cpv_input:
- self._package(cpv)
-
- def get_update_detail(self, pkgs):
- # TODO: a lot of informations are missing
-
- self.status(STATUS_INFO)
- self.allow_cancel(True)
- self.percentage(None)
-
- for pkg in pkgs:
- updates = []
- obsoletes = ""
- vendor_url = ""
- bugzilla_url = ""
- cve_url = ""
-
- cpv = self._id_to_cpv(pkg)
-
- if not self.pvar.portdb.cpv_exists(cpv):
- self.message(MESSAGE_COULD_NOT_FIND_PACKAGE, "could not find %s" % pkg)
-
- for cpv in self.pvar.vardb.match(portage.versions.pkgsplit(cpv)[0]):
- updates.append(cpv)
- updates = "&".join(updates)
-
- # temporarily set vendor_url = homepage
- homepage = self._get_metadata(cpv, ["HOMEPAGE"])[0]
- vendor_url = homepage
- issued = ""
- updated = ""
-
- self.update_detail(pkg, updates, obsoletes, vendor_url, bugzilla_url,
- cve_url, "none", "No update text", "No ChangeLog",
- UPDATE_STATE_STABLE, issued, updated)
-
- def get_updates(self, filters):
- # NOTES:
- # because of a lot of things related to Gentoo,
- # only world and system packages are can be listed as updates
- # _except_ for security updates
-
- # UPDATE TYPES:
- # - blocked: wait for feedbacks
- # - low: TODO: --newuse
- # - normal: default
- # - important: none atm
- # - security: from @security
-
- # FILTERS:
- # - installed: try to update non-installed packages and call me ;)
- # - free: ok
- # - newest: ok
-
- self.status(STATUS_INFO)
- self.allow_cancel(True)
- self.percentage(None)
-
- fltlist = filters.split(';')
-
- update_candidates = []
- cpv_updates = {}
- cpv_downgra = {}
-
- # get system and world packages
- for s in ["system", "world"]:
- set = portage.sets.base.InternalPackageSet(
- initial_atoms=self.pvar.root_config.setconfig.getSetAtoms(s))
- for atom in set:
- update_candidates.append(atom.cp)
-
- # check if a candidate can be updated
- for cp in update_candidates:
- cpv_list_inst = self.pvar.vardb.match(cp)
- cpv_list_avai = self.pvar.portdb.match(cp)
-
- cpv_dict_inst = self._get_cpv_slotted(cpv_list_inst)
- cpv_dict_avai = self._get_cpv_slotted(cpv_list_avai)
-
- dict_upda = {}
- dict_down = {}
-
- # candidate slots are installed slots
- slots = cpv_dict_inst.keys()
- slots.reverse()
-
- for s in slots:
- cpv_list_updates = []
- cpv_inst = cpv_dict_inst[s][0] # only one install per slot
-
- # the slot can be outdated (not in the tree)
- if s not in cpv_dict_avai:
- break
-
- tmp_list_avai = cpv_dict_avai[s]
- tmp_list_avai.reverse()
-
- for cpv in tmp_list_avai:
- if self._cmp_cpv(cpv_inst, cpv) == -1:
- cpv_list_updates.append(cpv)
- else: # because the list is sorted
- break
-
- # no update for this slot
- if len(cpv_list_updates) == 0:
- if [cpv_inst] == self.pvar.portdb.visible([cpv_inst]):
- break # really no update
- else:
- # that's actually a downgrade or even worst
- if len(tmp_list_avai) == 0:
- break # this package is not known in the tree...
- else:
- dict_down[s] = [tmp_list_avai.pop()]
-
- cpv_list_updates = self._filter_free(cpv_list_updates, fltlist)
-
- if len(cpv_list_updates) == 0:
- break
-
- if FILTER_NEWEST in fltlist:
- best_cpv = portage.versions.best(cpv_list_updates)
- cpv_list_updates = [best_cpv]
-
- dict_upda[s] = cpv_list_updates
-
- if len(dict_upda) != 0:
- cpv_updates[cp] = dict_upda
- if len(dict_down) != 0:
- cpv_downgra[cp] = dict_down
-
- # get security updates
- for atom in portage.sets.base.InternalPackageSet(
- initial_atoms=self.pvar.root_config.setconfig.getSetAtoms("security")):
- # send update message and remove atom from cpv_updates
- if atom.cp in cpv_updates:
- slot = self._get_metadata(atom.cpv, ["SLOT"])[0]
- if slot in cpv_updates[atom.cp]:
- tmp_cpv_list = cpv_updates[atom.cp][slot][:]
- for cpv in tmp_cpv_list:
- if self._cmp_cpv(cpv, atom.cpv) >= 0:
- # cpv is a security update and removed from list
- cpv_updates[atom.cp][slot].remove(cpv)
- self._package(cpv, INFO_SECURITY)
- else: # update also non-world and non-system packages if security
- self._package(atom.cpv, INFO_SECURITY)
-
- # downgrades
- for cp in cpv_downgra:
- for slot in cpv_downgra[cp]:
- for cpv in cpv_downgra[cp][slot]:
- self._package(cpv, INFO_IMPORTANT)
-
- # normal updates
- for cp in cpv_updates:
- for slot in cpv_updates[cp]:
- for cpv in cpv_updates[cp][slot]:
- self._package(cpv, INFO_NORMAL)
-
- def simulate_install_packages(self, pkgs):
- return self._install_packages(False, pkgs, simulate=True)
-
- def install_packages(self, only_trusted, pkgs):
- return self._install_packages(False, pkgs)
-
- def _install_packages(self, only_trusted, pkgs, simulate=False):
- # NOTES:
- # can't install an already installed packages
- # even if it happens to be needed in Gentoo but probably not this API
- # TODO: every merged pkg should emit self.package()
- # see around _emerge.Scheduler.Scheduler
-
- self.status(STATUS_RUNNING)
- self.allow_cancel(False)
- self.percentage(None)
-
- cpv_list = []
-
- for pkg in pkgs:
- cpv = self._id_to_cpv(pkg)
-
- if not self._is_cpv_valid(cpv):
- self.error(ERROR_PACKAGE_NOT_FOUND,
- "Package %s was not found" % pkg)
- continue
-
- if self._is_installed(cpv):
- self.error(ERROR_PACKAGE_ALREADY_INSTALLED,
- "Package %s is already installed" % pkg)
- continue
-
- cpv_list.append('=' + cpv)
-
- # only_trusted isn't supported
- # but better to show it after important errors
- if only_trusted:
- self.error(ERROR_MISSING_GPG_SIGNATURE,
- "Portage backend does not support GPG signature")
- return
-
- # creating installation depgraph
- myopts = {}
- favorites = []
- myparams = _emerge.create_depgraph_params.create_depgraph_params(
- myopts, "")
-
- self.status(STATUS_DEP_RESOLVE)
-
- depgraph = _emerge.depgraph.depgraph(self.pvar.settings,
- self.pvar.trees, myopts, myparams, None)
- retval, favorites = depgraph.select_files(cpv_list)
- if not retval:
- self.error(ERROR_DEP_RESOLUTION_FAILED,
- "Wasn't able to get dependency graph")
- return
-
- # check fetch restrict, can stop the function via error signal
- self._check_fetch_restrict(depgraph.altlist())
-
- self.status(STATUS_INSTALL)
-
- if simulate:
- return
-
- # get elog messages
- portage.elog.add_listener(self._elog_listener)
-
- try:
- self._block_output()
- # compiling/installing
- mergetask = _emerge.Scheduler.Scheduler(self.pvar.settings,
- self.pvar.trees, self.pvar.mtimedb, myopts, None,
- depgraph.altlist(), favorites, depgraph.schedulerGraph())
- rval = mergetask.merge()
- finally:
- self._unblock_output()
-
- # when an error is found print error messages
- if rval != os.EX_OK:
- self._send_merge_error(ERROR_PACKAGE_FAILED_TO_INSTALL)
-
- # show elog messages and clean
- portage.elog.remove_listener(self._elog_listener)
- for msg in self._elog_messages:
- # TODO: use specific message ?
- self.message(MESSAGE_UNKNOWN, msg)
- self._elog_messages = []
-
- self._signal_config_update()
-
- def refresh_cache(self, force):
- # NOTES: can't manage progress even if it could be better
- # TODO: do not wait for exception, check timestamp
- # TODO: message if overlay repo has changed (layman)
- self.status(STATUS_REFRESH_CACHE)
- self.allow_cancel(False)
- self.percentage(None)
-
- myopts = {'--quiet': True}
-
- # get installed and available dbs
- installed_layman_db = layman.db.DB(layman.config.Config())
-
- if force:
- timestamp_path = os.path.join(
- self.pvar.settings["PORTDIR"], "metadata", "timestamp.chk")
- if os.access(timestamp_path, os.F_OK):
- os.remove(timestamp_path)
-
- try:
- self._block_output()
- for o in installed_layman_db.overlays.keys():
- installed_layman_db.sync(o, quiet=True)
- _emerge.actions.action_sync(self.pvar.settings, self.pvar.trees,
- self.pvar.mtimedb, myopts, "")
- except:
- self.error(ERROR_INTERNAL_ERROR, traceback.format_exc())
- finally:
- self._unblock_output()
-
- def remove_packages(self, allowdep, autoremove, pkgs):
- return self._remove_packages(allowdep, autoremove, pkgs)
-
- def simulate_remove_packages(self, pkgs):
- return self._remove_packages(True, False, pkgs, simulate=True)
-
- def _remove_packages(self, allowdep, autoremove, pkgs, simulate=False):
- # TODO: every to-be-removed pkg should emit self.package()
- # see around _emerge.Scheduler.Scheduler
- self.status(STATUS_RUNNING)
- self.allow_cancel(False)
- self.percentage(None)
-
- cpv_list = []
- packages = []
- required_packages = []
- system_packages = []
-
- # get system packages
- set = portage.sets.base.InternalPackageSet(
- initial_atoms=self.pvar.root_config.setconfig.getSetAtoms("system"))
- for atom in set:
- system_packages.append(atom.cp)
-
- # create cpv_list
- for pkg in pkgs:
- cpv = self._id_to_cpv(pkg)
-
- if not self._is_cpv_valid(cpv):
- self.error(ERROR_PACKAGE_NOT_FOUND,
- "Package %s was not found" % pkg)
- continue
-
- if not self._is_installed(cpv):
- self.error(ERROR_PACKAGE_NOT_INSTALLED,
- "Package %s is not installed" % pkg)
- continue
-
- # stop removal if a package is in the system set
- if portage.versions.pkgsplit(cpv)[0] in system_packages:
- self.error(ERROR_CANNOT_REMOVE_SYSTEM_PACKAGE,
- "Package %s is a system package. If you really want to remove it, please use portage" % pkg)
- continue
-
- cpv_list.append(cpv)
-
- # backend do not implement autoremove
- if autoremove:
- self.message(MESSAGE_AUTOREMOVE_IGNORED,
- "Portage backend do not implement autoremove option")
-
- # get packages needing candidates for removal
- required_packages = self._get_required_packages(cpv_list, recursive=True)
-
- # if there are required packages, allowdep must be on
- if required_packages and not allowdep:
- self.error(ERROR_DEP_RESOLUTION_FAILED,
- "Could not perform remove operation has packages are needed by other packages")
- return
-
- # first, we add required packages
- for p in required_packages:
- package = _emerge.Package.Package(
- type_name=p.type_name,
- built=p.built,
- installed=p.installed,
- root_config=p.root_config,
- cpv=p.cpv,
- metadata=p.metadata,
- operation='uninstall')
- packages.append(package)
-
- # and now, packages we want really to remove
- for cpv in cpv_list:
- metadata = self._get_metadata(cpv, [],
- in_dict=True, add_cache_keys=True)
- package = _emerge.Package.Package(
- type_name="ebuild",
- built=True,
- installed=True,
- root_config=self.pvar.root_config,
- cpv=cpv,
- metadata=metadata,
- operation="uninstall")
- packages.append(package)
-
- if simulate:
- return
-
- # need to define favorites to remove packages from world set
- favorites = []
- for p in packages:
- favorites.append('=' + p.cpv)
-
- # get elog messages
- portage.elog.add_listener(self._elog_listener)
-
- # now, we can remove
- try:
- self._block_output()
- mergetask = _emerge.Scheduler.Scheduler(self.pvar.settings,
- self.pvar.trees, self.pvar.mtimedb, mergelist=packages,
- myopts={}, spinner=None, favorites=favorites, digraph=None)
- rval = mergetask.merge()
- finally:
- self._unblock_output()
-
- # when an error is found print error messages
- if rval != os.EX_OK:
- self._send_merge_error(ERROR_PACKAGE_FAILED_TO_REMOVE)
-
- # show elog messages and clean
- portage.elog.remove_listener(self._elog_listener)
- for msg in self._elog_messages:
- # TODO: use specific message ?
- self.message(MESSAGE_UNKNOWN, msg)
- self._elog_messages = []
-
- def repo_enable(self, repoid, enable):
- # NOTES: use layman API >= 1.2.3
- self.status(STATUS_INFO)
- self.allow_cancel(True)
- self.percentage(None)
-
- # special case: trying to work with gentoo repo
- if repoid == 'gentoo':
- if not enable:
- self.error(ERROR_CANNOT_DISABLE_REPOSITORY,
- "gentoo repository can't be disabled")
- return
-
- # get installed and available dbs
- installed_layman_db = layman.db.DB(layman.config.Config())
- available_layman_db = layman.db.RemoteDB(layman.config.Config())
-
- # check now for repoid so we don't have to do it after
- if not repoid in available_layman_db.overlays.keys():
- self.error(ERROR_REPO_NOT_FOUND,
- "Repository %s was not found" % repoid)
- return
-
- # disabling (removing) a db
- # if repository already disabled, ignoring
- if not enable and self._is_repo_enabled(installed_layman_db, repoid):
- try:
- installed_layman_db.delete(installed_layman_db.select(repoid))
- except Exception, e:
- self.error(ERROR_INTERNAL_ERROR,
- "Failed to disable repository "+repoid+" : "+str(e))
- return
-
- # enabling (adding) a db
- # if repository already enabled, ignoring
- if enable and not self._is_repo_enabled(installed_layman_db, repoid):
- try:
- # TODO: clean the trick to prevent outputs from layman
- self._block_output()
- installed_layman_db.add(available_layman_db.select(repoid),
- quiet=True)
- self._unblock_output()
- except Exception, e:
- self._unblock_output()
- self.error(ERROR_INTERNAL_ERROR,
- "Failed to enable repository "+repoid+" : "+str(e))
- return
-
- def resolve(self, filters, pkgs):
- self.status(STATUS_QUERY)
- self.allow_cancel(True)
- self.percentage(0)
-
- fltlist = filters.split(';')
- cp_list = self._get_all_cp(fltlist)
- nb_cp = float(len(cp_list))
- cp_processed = 0.0
-
- reg_expr = []
- for pkg in pkgs:
- reg_expr.append("^" + re.escape(pkg) + "$")
- reg_expr = "|".join(reg_expr)
-
- # specifications says "be case sensitive"
- s = re.compile(reg_expr)
-
- for cp in cp_list:
- if s.match(cp):
- for cpv in self._get_all_cpv(cp, fltlist):
- self._package(cpv)
-
- cp_processed += 100.0
- self.percentage(int(cp_processed/nb_cp))
-
- self.percentage(100)
-
- def search_details(self, filters, keys):
- # NOTES: very bad performance
- self.status(STATUS_QUERY)
- self.allow_cancel(True)
- self.percentage(0)
-
- fltlist = filters.split(';')
- cp_list = self._get_all_cp(fltlist)
- nb_cp = float(len(cp_list))
- cp_processed = 0.0
- search_list = self._get_search_list(keys)
-
- for cp in cp_list:
- # unfortunatelly, everything is related to cpv, not cp
- # can't filter cp
- cpv_list = []
-
- # newest filter can't be executed now
- # because some cpv are going to be filtered by search conditions
- # and newest filter could be alterated
- for cpv in self._get_all_cpv(cp, fltlist, filter_newest=False):
- match = True
- metadata = self._get_metadata(cpv,
- ["DESCRIPTION", "HOMEPAGE", "IUSE",
- "LICENSE", "repository", "SLOT"],
- in_dict=True)
- # update LICENSE to correspond to system settings
- metadata["LICENSE"] = self._get_real_license_str(cpv, metadata)
- for s in search_list:
- found = False
- for x in metadata:
- if s.search(metadata[x]):
- found = True
- break
- if not found:
- match = False
- break
- if match:
- cpv_list.append(cpv)
-
- # newest filter
- cpv_list = self._filter_newest(cpv_list, fltlist)
-
- for cpv in cpv_list:
- self._package(cpv)
-
- cp_processed += 100.0
- self.percentage(int(cp_processed/nb_cp))
-
- self.percentage(100)
-
- def search_file(self, filters, key):
- # FILTERS:
- # - ~installed is not accepted (error)
- # - free: ok
- # - newest: as only installed, by himself
- self.status(STATUS_QUERY)
- self.allow_cancel(True)
- self.percentage(0)
-
- fltlist = filters.split(';')
-
- if FILTER_NOT_INSTALLED in fltlist:
- self.error(ERROR_CANNOT_GET_FILELIST,
- "search-file isn't available with ~installed filter")
- return
-
- cpv_list = self.pvar.vardb.cpv_all()
- nb_cpv = 0.0
- cpv_processed = 0.0
- is_full_path = True
-
- if key[0] != "/":
- is_full_path = False
- key = re.escape(key)
- searchre = re.compile("/" + key + "$", re.IGNORECASE)
-
- # free filter
- cpv_list = self._filter_free(cpv_list, fltlist)
- nb_cpv = float(len(cpv_list))
-
- for cpv in cpv_list:
- for f in self._get_file_list(cpv):
- if (is_full_path and key == f) \
- or (not is_full_path and searchre.search(f)):
- self._package(cpv)
- break
-
- cpv_processed += 100.0
- self.percentage(int(cpv_processed/nb_cpv))
-
- self.percentage(100)
-
- def search_group(self, filters, groups):
- # TODO: filter unknown groups before searching ? (optimization)
- self.status(STATUS_QUERY)
- self.allow_cancel(True)
- self.percentage(0)
-
- fltlist = filters.split(';')
- cp_list = self._get_all_cp(fltlist)
- nb_cp = float(len(cp_list))
- cp_processed = 0.0
-
- for cp in cp_list:
- for group in groups:
- if self._get_pk_group(cp) == group:
- for cpv in self._get_all_cpv(cp, fltlist):
- self._package(cpv)
-
- cp_processed += 100.0
- self.percentage(int(cp_processed/nb_cp))
-
- self.percentage(100)
-
- def search_name(self, filters, keys_list):
- # searching for all keys in package name
- # also filtering by categories if categery is specified in a key
- # keys contain more than one category name, no results can be found
- self.status(STATUS_QUERY)
- self.allow_cancel(True)
- self.percentage(0)
-
- categories = []
- for k in keys_list[:]:
- if "/" in k:
- cat, cp = portage.versions.catsplit(k)
- categories.append(cat)
- keys_list[keys_list.index(k)] = cp
-
- category_filter = None
- if len(categories) > 1:
- # nothing will be found because we have two cat/pkg
- # with a AND operator search
- return
- elif len(categories) == 1:
- category_filter = categories[0]
-
- # do not use self._get_search_list because of this category feature
- search_list = []
- for k in keys_list:
- # not done entirely by pk-transaction
- k = re.escape(k)
- search_list.append(re.compile(k, re.IGNORECASE))
-
- fltlist = filters.split(';')
- cp_list = self._get_all_cp(fltlist)
- nb_cp = float(len(cp_list))
- cp_processed = 0.0
-
- for cp in cp_list:
- if category_filter:
- cat, pkg_name = portage.versions.catsplit(cp)
- if cat != category_filter:
- continue
- else:
- pkg_name = portage.versions.catsplit(cp)[1]
- found = True
-
- # pkg name has to correspond to _every_ keys
- for s in search_list:
- if not s.search(pkg_name):
- found = False
- break
- if found:
- for cpv in self._get_all_cpv(cp, fltlist):
- self._package(cpv)
-
- cp_processed += 100.0
- self.percentage(int(cp_processed/nb_cp))
-
- self.percentage(100)
-
- def update_packages(self, only_trusted, pkgs):
- return self._update_packages(only_trusted, pkgs)
-
- def simulate_update_packages(self, pkgs):
- return self._update_packages(False, pkgs, simulate=True)
-
- def _update_packages(self, only_trusted, pkgs, simulate=False):
- # TODO: manage errors
- # TODO: manage config file updates
- # TODO: every updated pkg should emit self.package()
- # see around _emerge.Scheduler.Scheduler
-
- self.status(STATUS_RUNNING)
- self.allow_cancel(False)
- self.percentage(None)
-
- cpv_list = []
-
- for pkg in pkgs:
- cpv = self._id_to_cpv(pkg)
-
- if not self._is_cpv_valid(cpv):
- self.error(ERROR_UPDATE_NOT_FOUND,
- "Package %s was not found" % pkg)
- continue
-
- cpv_list.append('=' + cpv)
-
- # only_trusted isn't supported
- # but better to show it after important errors
- if only_trusted:
- self.error(ERROR_MISSING_GPG_SIGNATURE,
- "Portage backend does not support GPG signature")
- return
-
- # creating update depgraph
- myopts = {}
- favorites = []
- myparams = _emerge.create_depgraph_params.create_depgraph_params(
- myopts, "")
-
- self.status(STATUS_DEP_RESOLVE)
-
- depgraph = _emerge.depgraph.depgraph(self.pvar.settings,
- self.pvar.trees, myopts, myparams, None)
- retval, favorites = depgraph.select_files(cpv_list)
- if not retval:
- self.error(ERROR_DEP_RESOLUTION_FAILED,
- "Wasn't able to get dependency graph")
- return
-
- # check fetch restrict, can stop the function via error signal
- self._check_fetch_restrict(depgraph.altlist())
-
- self.status(STATUS_INSTALL)
-
- if simulate:
- return
-
- # get elog messages
- portage.elog.add_listener(self._elog_listener)
-
- try:
- self._block_output()
- # compiling/installing
- mergetask = _emerge.Scheduler.Scheduler(self.pvar.settings,
- self.pvar.trees, self.pvar.mtimedb, myopts, None,
- depgraph.altlist(), favorites, depgraph.schedulerGraph())
- rval = mergetask.merge()
- finally:
- self._unblock_output()
-
- # when an error is found print error messages
- if rval != os.EX_OK:
- self._send_merge_error(ERROR_PACKAGE_FAILED_TO_INSTALL)
-
- # show elog messages and clean
- portage.elog.remove_listener(self._elog_listener)
- for msg in self._elog_messages:
- # TODO: use specific message ?
- self.message(MESSAGE_UNKNOWN, msg)
- self._elog_messages = []
-
- self._signal_config_update()
-
- def update_system(self, only_trusted):
- self.status(STATUS_RUNNING)
- self.allow_cancel(False)
- self.percentage(None)
-
- if only_trusted:
- self.error(ERROR_MISSING_GPG_SIGNATURE,
- "Portage backend does not support GPG signature")
- return
-
- myopts = {}
- myopts["--deep"] = True
- myopts["--newuse"] = True
- myopts["--update"] = True
-
- myparams = _emerge.create_depgraph_params.create_depgraph_params(
- myopts, "")
-
- self.status(STATUS_DEP_RESOLVE)
-
- # creating list of ebuilds needed for the system update
- # using backtrack_depgraph to prevent errors
- retval, depgraph, _ = _emerge.depgraph.backtrack_depgraph(
- self.pvar.settings, self.pvar.trees, myopts, myparams, "",
- ["@system", "@world"], None)
- if not retval:
- self.error(ERROR_INTERNAL_ERROR,
- "Wasn't able to get dependency graph")
- return
-
- # check fetch restrict, can stop the function via error signal
- self._check_fetch_restrict(depgraph.altlist())
-
- self.status(STATUS_INSTALL)
-
- # get elog messages
- portage.elog.add_listener(self._elog_listener)
-
- try:
- self._block_output()
- # compiling/installing
- mergetask = _emerge.Scheduler.Scheduler(self.pvar.settings,
- self.pvar.trees, self.pvar.mtimedb, myopts, None,
- depgraph.altlist(), None, depgraph.schedulerGraph())
- rval = mergetask.merge()
- finally:
- self._unblock_output()
-
- # when an error is found print error messages
- if rval != os.EX_OK:
- self._send_merge_error(ERROR_PACKAGE_FAILED_TO_INSTALL)
-
- # show elog messages and clean
- portage.elog.remove_listener(self._elog_listener)
- for msg in self._elog_messages:
- # TODO: use specific message ?
- self.message(MESSAGE_UNKNOWN, msg)
- self._elog_messages = []
-
- self._signal_config_update()
-
-def main():
- backend = PackageKitPortageBackend("")
- backend.dispatcher(sys.argv[1:])
-
-if __name__ == "__main__":
- main()
diff --git a/src/runner.c b/src/runner.c
deleted file mode 100644
index 61c342a..0000000
--- a/src/runner.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Compile command :
- * gcc -o runner -W -Wall -g --std=c99 runner.c
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include "runner.h"
-
-void stdoutWritten(char*);
-
-struct Runner {
- void *writeStdout;
-};
-
-int main(int argc, char* argv[])
-{
- // Tries to compare 2 packages version.
- /*if (argc < 3)
- {
- printf("Please provide 2 packages.\n");
- return -1;
- }
-
- char *str = malloc((strlen(argv[1]) + strlen(argv[2]) + 2) * sizeof(char));
-
- sprintf(str, "%s %s", argv[1], argv[2]);
- */
- Runner *r = createRunner();
- r->writeStdout = stdoutWritten;
- int ret = execute(r, "");
-
- if (ret < 0)
- printf("Execution error\n");
-
- freeRunner(r);
-
- return 0;
-}
-
-void stdoutWritten(char *data)
-{
- printf("From program : %s\n", data);
-}
-
-Runner *createRunner()
-{
- Runner *ret = malloc(sizeof(Runner));
- return ret;
-}
-
-int execute(Runner *r, char *args)
-{
- r = r;
- int ret = fork();
- if (ret > 0)
- {
- printf("New PID = %d\n", ret);
- // Listening socket
- int fd = socket(AF_INET, SOCK_STREAM, 0);
- if (fd < 0)
- printf("ERROR opening socket\n");
-
- struct sockaddr_in serv_addr;
-
- memset(&serv_addr, 0, sizeof(serv_addr));
-
- int portno = 5555;
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- serv_addr.sin_port = htons(portno);
-
- if ((ret = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) < 0)
- {
- printf("ERROR on binding : %d, %d (%s)\n", ret, errno, strerror(errno));
- return ret;
- }
-
- if ((ret = listen(fd, 5)) < 0)
- printf("ERROR on listening : %d, %d (%s)\n", ret, errno, strerror(errno));
-
- while(1)
- {
- unsigned int clilen = sizeof(serv_addr);
- int newfd = accept(fd, (struct sockaddr *) &serv_addr, &clilen);
-
- char buf[256];
- int n = read(newfd, buf, 255);
- buf[n] = '\0';
- printf("received : %s\n", buf);
- }
-
- return ret;
- }
-
- int fd = socket(AF_INET, SOCK_STREAM, 0);
- if (fd < 0)
- printf("ERROR opening socket\n");
-
- struct sockaddr_in serv_addr;
-
- memset(&serv_addr, 0, sizeof(serv_addr));
-
- int portno = 5555;
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- serv_addr.sin_port = htons(portno);
-
- if ((ret = connect(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) < 0)
- {
- printf("ERROR on connecting : %d, %d (%s)\n", ret, errno, strerror(errno));
- return ret;
- }
-
- dup2(fd, STDOUT_FILENO);
- ret = execl("./test.py", "test.py", "app-portage/kuroo4-4.2", "app-portage/kuroo4-4.3", NULL);
- printf("execl: (%d) %s\n", errno, strerror(errno));
- return ret;
-}
-
-void freeRunner(Runner *r)
-{
- free(r);
-}
diff --git a/src/runner.h b/src/runner.h
deleted file mode 100644
index c087895..0000000
--- a/src/runner.h
+++ /dev/null
@@ -1,6 +0,0 @@
-
-typedef struct Runner Runner;
-
-Runner *createRunner();
-int execute(Runner*, char*);
-void freeRunner(Runner*);
diff --git a/src/test.py b/src/test.py
deleted file mode 100755
index fadcbdf..0000000
--- a/src/test.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/python
-# !!!! WARNING !!!!
-# Test file : It's not safe, can break your system and make your life miserable, you've been warned.
-# !!!! WARNING !!!!
-
-from portage import *
-
-ret = pkgcmp(pkgsplit(sys.argv[1]), pkgsplit(sys.argv[2]))
-
-if ret == 0 :
- print "same"
-elif ret == -1:
- print "less"
-else:
- print "more"