diff options
Diffstat (limited to 'portato/backend')
-rw-r--r-- | portato/backend/__init__.py | 22 | ||||
-rw-r--r-- | portato/backend/package.py | 114 | ||||
-rw-r--r-- | portato/backend/portage_helper.py | 131 |
3 files changed, 223 insertions, 44 deletions
diff --git a/portato/backend/__init__.py b/portato/backend/__init__.py index ef6811f..ce244c5 100644 --- a/portato/backend/__init__.py +++ b/portato/backend/__init__.py @@ -10,24 +10,24 @@ # # Written by René 'Necoro' Neumann <necoro@necoro.net> -import sys +import sys, copy +from threading import Lock -# insert the gentoolkit-location into syspath -sys.path.insert(0, "/usr/lib/gentoolkit/pym") - -# import gentoolkit and portage -import gentoolkit +# import portage import portage +# portage tree vars +settingslock = Lock() +settings = portage.config(clone=portage.settings, config_incrementals = copy.deepcopy(portage.settings.incrementals)) +porttree = portage.db[portage.root]["porttree"] +vartree = portage.db[portage.root]["vartree"] +virtuals = portage.db[portage.root]["virtuals"] +trees = portage.db + # this is set to "var/lib/portage/world" by default - so we add the leading / portage.WORLD_FILE = portage.settings["ROOT"]+portage.WORLD_FILE portage.settings = None # we use our own one ... -# portage tree vars -porttree = gentoolkit.porttree -vartree = gentoolkit.vartree -trees = portage.db - # import our packages from exceptions import * from package import * diff --git a/portato/backend/package.py b/portato/backend/package.py index 82e0b22..6e32776 100644 --- a/portato/backend/package.py +++ b/portato/backend/package.py @@ -15,12 +15,12 @@ from portato.helper import * from portage_helper import * import flags -import portage, portage_dep, gentoolkit +import portage, portage_dep from portage_util import unique_array import types -class Package (gentoolkit.Package): +class Package: """This is a subclass of the gentoolkit.Package-class which a lot of additional functionality we need in Portato.""" def __init__ (self, cpv): @@ -29,14 +29,30 @@ class Package (gentoolkit.Package): @param cpv: The cpv or gentoolkit.Package which describes the package to create. @type cpv: string (cat/pkg-ver) or gentoolkit.Package-object.""" - if isinstance(cpv, gentoolkit.Package): - cpv = cpv.get_cpv() - gentoolkit.Package.__init__(self, cpv) + self._cpv = cpv + self._scpv = portage.catpkgsplit(self._cpv) + + if not self._scpv: + raise FatalError("invalid cpv: %s" % cpv) + self._db = None + self._settings = settings + self._settingslock = settingslock + try: - self._status = portage.getmaskingstatus(self.get_cpv(), settings = gentoolkit.settings) + self._status = portage.getmaskingstatus(self.get_cpv(), settings = settings) except KeyError: # package is not located in the system self._status = None + def is_installed(self): + """Returns true if this package is installed (merged)""" + self._initdb() + return os.path.exists(self._db.getpath()) + + def is_overlay(self): + """Returns true if the package is in an overlay.""" + dir,ovl = portage.portdb.findname2(self._cpv) + return ovl != settings["PORTDIR"] + def is_in_system (self): """Returns False if the package could not be found in the portage system. @@ -302,6 +318,10 @@ class Package (gentoolkit.Package): return dep_pkgs + def get_cpv(self): + """Returns full Category/Package-Version string""" + return self._cpv + def get_cp (self): """Returns the cp-string. @@ -310,6 +330,88 @@ class Package (gentoolkit.Package): return self.get_category()+"/"+self.get_name() + def get_name(self): + """Returns base name of package, no category nor version""" + return self._scpv[1] + + def get_version(self): + """Returns version of package, with revision number""" + v = self._scpv[2] + if self._scpv[3] != "r0": + v += "-" + self._scpv[3] + return v + + def get_category(self): + """Returns category of package""" + return self._scpv[0] + + def get_settings(self, key): + """Returns the value of the given key for this package (useful + for package.* files.""" + self._settingslock.acquire() + self._settings.setcpv(self._cpv) + v = self._settings[key] + self._settingslock.release() + return v + + def get_ebuild_path(self,in_vartree=0): + """Returns the complete path to the .ebuild file""" + if in_vartree: + return vartree.getebuildpath(self._cpv) + else: + return portage.portdb.findname(self._cpv) + + def get_package_path(self): + """Returns the path to where the ChangeLog, Manifest, .ebuild files reside""" + p = self.get_ebuild_path() + sp = p.split("/") + if len(sp): + return string.join(sp[:-1],"/") + + def get_env_var(self, var, tree=""): + """Returns one of the predefined env vars DEPEND, RDEPEND, SRC_URI,....""" + if tree == "": + mytree = vartree + if not self.is_installed(): + mytree = porttree + else: + mytree = tree + r = mytree.dbapi.aux_get(self._cpv,[var]) + if not r: + raise FatalError("Could not find the package tree") + if len(r) != 1: + raise FatalError("Should only get one element!") + return r[0] + + def get_use_flags(self): + """Returns the USE flags active at time of installation""" + self._initdb() + if self.is_installed(): + return self._db.getfile("USE") + return "" + + def compare_version(self,other): + """Compares this package's version to another's CPV; returns -1, 0, 1""" + v1 = self._scpv + v2 = portage.catpkgsplit(other.get_cpv()) + # if category is different + if v1[0] != v2[0]: + return cmp(v1[0],v2[0]) + # if name is different + elif v1[1] != v2[1]: + return cmp(v1[1],v2[1]) + # Compaare versions + else: + return portage.pkgcmp(v1[1:],v2[1:]) + + def _initdb(self): + """Internal helper function; loads package information from disk, + when necessary""" + if not self._db: + cat = self.get_category() + pnv = self.get_name()+"-"+self.get_version() + self._db = portage.dblink(cat,pnv,settings["ROOT"],settings) + def matches (self, criterion): """This checks, whether this package matches a specific verisioning criterion - e.g.: "<=net-im/foobar-1.2". diff --git a/portato/backend/portage_helper.py b/portato/backend/portage_helper.py index 6e8fc84..1726323 100644 --- a/portato/backend/portage_helper.py +++ b/portato/backend/portage_helper.py @@ -12,7 +12,7 @@ import re, os, copy -import portage, gentoolkit +import portage from portage_util import unique_array from portato.backend import * @@ -76,7 +76,30 @@ def find_packages (search_key, masked=False): @returns: list of found packages @rtype: backend.Package[]""" - return geneticize_list(gentoolkit.find_packages(search_key, masked)) + try: + if masked: + t = portage.db["/"]["porttree"].dbapi.xmatch("match-all", search_key) + t += portage.db["/"]["vartree"].dbapi.match(search_key) + else: + t = portage.db["/"]["porttree"].dbapi.match(search_key) + t += portage.db["/"]["vartree"].dbapi.match(search_key) + # catch the "amgigous package" Exception + except ValueError, e: + if type(e[0]) == types.ListType: + t = [] + for cp in e[0]: + if masked: + t += portage.db["/"]["porttree"].dbapi.xmatch("match-all", cp) + t += portage.db["/"]["vartree"].dbapi.match(cp) + else: + t += portage.db["/"]["porttree"].dbapi.match(cp) + t += portage.db["/"]["vartree"].dbapi.match(cp) + else: + raise ValueError(e) + # Make the list of packages unique + t = unique_array(t) + t.sort() + return geneticize_list(t) def find_installed_packages (search_key, masked=False): """This returns a list of packages which have to fit exactly. Additionally ranges like '<,>,=,~,!' et. al. are possible. @@ -89,7 +112,18 @@ def find_installed_packages (search_key, masked=False): @returns: list of found packages @rtype: backend.Package[]""" - return geneticize_list(gentoolkit.find_installed_packages(search_key, masked)) + try: + t = portage.db["/"]["vartree"].dbapi.match(search_key) + # catch the "amgigous package" Exception + except ValueError, e: + if type(e[0]) == types.ListType: + t = [] + for cp in e[0]: + t += portage.db["/"]["vartree"].dbapi.match(cp) + else: + raise ValueError(e) + + return geneticize_list(t) def find_system_packages (): """Looks for all packages saved as "system-packages". @@ -97,8 +131,18 @@ def find_system_packages (): @returns: a tuple of (resolved_packages, unresolved_packages). @rtype: (backend.Package[], backend.Package[])""" - list = gentoolkit.find_system_packages() - return (geneticize_list(list[0]), geneticize_list(list[1])) + pkglist = settings.packages + resolved = [] + unresolved = [] + for x in pkglist: + cpv = x.strip() + if len(cpv) and cpv[0] == "*": + pkg = find_best_match(cpv) + if pkg: + resolved.append(pkg) + else: + unresolved.append(cpv) + return (geneticize_list(resolved), geneticize_list(unresolved)) def find_world_packages (): """Looks for all packages saved in the world-file. @@ -106,8 +150,19 @@ def find_world_packages (): @returns: a tuple of (resolved_packages, unresolved_packages). @rtype: (backend.Package[], backend.Package[])""" - list = gentoolkit.find_world_packages() - return geneticize_list(list[0]),geneticize_list(list[1]) + f = open(portage.WORLD_FILE) + pkglist = f.readlines() + resolved = [] + unresolved = [] + for x in pkglist: + cpv = x.strip() + if len(cpv) and cpv[0] != "#": + pkg = find_best_match(cpv) + if pkg: + resolved.append(pkg) + else: + unresolved.append(cpv) + return (geneticize_list(resolved), geneticize_list(unresolved)) def find_all_installed_packages (name=None, withVersion=True): """Finds all installed packages matching a name or all if no name is specified. @@ -121,7 +176,11 @@ def find_all_installed_packages (name=None, withVersion=True): @rtype: backend.Package[] or cp-string[]""" if withVersion: - return geneticize_list(gentoolkit.find_all_installed_packages(find_lambda(name))) + t = vartree.dbapi.cpv_all() + if name: + t = filter(find_lambda(name),t) + return geneticize_list(t) + else: t = vartree.dbapi.cp_all() if name: @@ -136,7 +195,8 @@ def find_all_uninstalled_packages (name=None): @returns: all packages found @rtype: backend.Package[]""" - return geneticize_list(gentoolkit.find_all_uninstalled_packages(find_lambda(name))) + alist = find_all_packages(name) + return geneticize_list([x for x in alist if not x.is_installed()]) def find_all_packages (name=None, withVersion=True): """Finds all packages matching a name or all if no name is specified. @@ -149,15 +209,21 @@ def find_all_packages (name=None, withVersion=True): @returns: all packages/cp-strings found @rtype: backend.Package[] or cp-string[]""" + t = porttree.dbapi.cp_all() + t += vartree.dbapi.cp_all() + if name: + t = filter(find_lambda(name),t) + t = unique_array(t) + if (withVersion): - return geneticize_list(gentoolkit.find_all_packages(find_lambda(name))) + t2 = [] + for x in t: + t2 += porttree.dbapi.cp_list(x) + t2 += vartree.dbapi.cp_list(x) + t2 = unique_array(t2) + return geneticize_list(t2) else: - t = porttree.dbapi.cp_all() - t += vartree.dbapi.cp_all() - t = unique_array(t) - if name: - t = filter(find_lambda(name),t) - return t + return t; def find_all_world_packages (name=None): """Finds all world packages matching a name or all if no name is specified. @@ -214,7 +280,7 @@ def list_categories (name=None): @returns: all categories found @rtype: string[]""" - categories = gentoolkit.settings.categories + categories = settings.categories return filter(find_lambda(name), categories) def split_package_name (name): @@ -224,20 +290,31 @@ def split_package_name (name): @type name: string @returns: list: [category, name, version, rev] whereby rev is "r0" if not specified in the name @rtype: string[]""" - - return gentoolkit.split_package_name(name) + + r = portage.catpkgsplit(name) + if not r: + r = name.split("/") + if len(r) == 1: + return ["", name, "", "r0"] + else: + return r + ["", "r0"] + if r[0] == 'null': + r[0] = '' + return r def sort_package_list(pkglist): """Sorts a package list in the same manner portage does. @param pkglist: list to sort @type pkglist: Packages[]""" - - return gentoolkit.sort_package_list(pkglist) + + pkglist.sort(package.Package.compare_version) + return pkglist def reload_settings (): """Reloads portage.""" - gentoolkit.settings = portage.config(config_incrementals = copy.deepcopy(gentoolkit.settings.incrementals)) + global settings + settings = portage.config(config_incrementals = copy.deepcopy(settings.incrementals)) def update_world (newuse = False, deep = False): """Calculates the packages to get updated in an update world. @@ -259,7 +336,7 @@ def update_world (newuse = False, deep = False): packages.append(line) world.close() - sys = gentoolkit.settings.packages + sys = settings.packages for x in sys: if x[0] == "*": x = x[1:] @@ -268,9 +345,9 @@ def update_world (newuse = False, deep = False): # Remove everything that is package.provided from our list # This is copied from emerge.getlist() for atom in packages[:]: - for expanded_atom in portage.flatten(portage.dep_virtual([atom], gentoolkit.settings)): + for expanded_atom in portage.flatten(portage.dep_virtual([atom], settings)): mykey = portage.dep_getkey(expanded_atom) - if mykey in gentoolkit.settings.pprovideddict and portage.match_from_list(expanded_atom, settings.pprovideddict[mykey]): + if mykey in settings.pprovideddict and portage.match_from_list(expanded_atom, settings.pprovideddict[mykey]): packages.remove(atom) break @@ -342,7 +419,7 @@ def get_use_desc (flag, package = None): # fill cache if needed if use_descs == {} or local_use_descs == {}: # read use.desc - fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.desc") + fd = open(settings["PORTDIR"]+"/profiles/use.desc") for line in fd.readlines(): line = line.strip() if line != "" and line[0] != '#': @@ -351,7 +428,7 @@ def get_use_desc (flag, package = None): use_descs[fields[0]] = fields[1] # read use.local.desc - fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.local.desc") + fd = open(settings["PORTDIR"]+"/profiles/use.local.desc") for line in fd.readlines(): line = line.strip() if line != "" and line[0] != '#': |