summaryrefslogtreecommitdiff
path: root/portato/backend/portage
diff options
context:
space:
mode:
authornecoro <>2007-02-19 23:04:14 +0000
committernecoro <>2007-02-19 23:04:14 +0000
commitfba60a84b9a838ad32def950210a6b62d9bcdbff (patch)
treed581e4fa141851323a05d4500ad95afe50ed6e02 /portato/backend/portage
parentb4c88233aa6dabd2d9301350a240b8ddcf09255a (diff)
downloadportato-fba60a84b9a838ad32def950210a6b62d9bcdbff.tar.gz
portato-fba60a84b9a838ad32def950210a6b62d9bcdbff.tar.bz2
portato-fba60a84b9a838ad32def950210a6b62d9bcdbff.zip
Back to our own revision solution as the eclass-one checks _before_ updating
Diffstat (limited to '')
-rw-r--r--portato/backend/portage/__init__.py14
-rw-r--r--portato/backend/portage/package.py234
-rw-r--r--portato/backend/portage/settings.py55
-rw-r--r--portato/backend/portage/system.py370
-rw-r--r--portato/backend/portage_helper.py467
5 files changed, 673 insertions, 467 deletions
diff --git a/portato/backend/portage/__init__.py b/portato/backend/portage/__init__.py
new file mode 100644
index 0000000..e21278c
--- /dev/null
+++ b/portato/backend/portage/__init__.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+#
+# File: portato/backend/portage/__init__.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2006-2007 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+from system import PortageSystem
+from package import PortagePackage
diff --git a/portato/backend/portage/package.py b/portato/backend/portage/package.py
new file mode 100644
index 0000000..74a5107
--- /dev/null
+++ b/portato/backend/portage/package.py
@@ -0,0 +1,234 @@
+# -*- coding: utf-8 -*-
+#
+# File: portato/backend/portage/package.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2006-2007 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+from portato.helper import *
+from portato.backend.exceptions import *
+from portato.backend import flags, Package, system
+
+import portage, portage_dep
+from portage_util import unique_array
+
+import os.path
+
+class PortagePackage (Package):
+ """This is a class abstracting a normal package which can be installed for the portage-system."""
+
+ def __init__ (self, cpv):
+ """Constructor.
+
+ @param cpv: The cpv which describes the package to create.
+ @type cpv: string (cat/pkg-ver)"""
+
+ Package.__init__(self, cpv)
+ self._settings = system.settings
+ self._settingslock = system.settings.settingslock
+
+ self._trees = system.settings.trees
+
+ self.forced_flags = set()
+ self.forced_flags.update(self._settings.settings.usemask)
+ self.forced_flags.update(self._settings.settings.useforce)
+
+ try:
+ self._status = portage.getmaskingstatus(self.get_cpv(), settings = self._settings.settings)
+ except KeyError: # package is not located in the system
+ self._status = None
+
+ def is_installed(self):
+ return self._settings.vartree.dbapi.cpv_exists(self._cpv)
+
+ def is_overlay(self):
+ dir,ovl = self._settings.porttree.dbapi.findname2(self._cpv)
+ return ovl != self._settings.settings["PORTDIR"]
+
+ def is_in_system (self):
+ return (self._status != None)
+
+ def is_missing_keyword(self):
+ if self._status and "missing keyword" in self._status:
+ return True
+ return False
+
+ def is_testing(self, use_keywords = False):
+ testArch = "~" + self.get_settings("ARCH")
+ if not use_keywords: # keywords are NOT taken into account
+ if testArch in self.get_env_var("KEYWORDS").split():
+ return True
+ return False
+
+ else: # keywords are taken into account
+ status = flags.new_testing_status(self.get_cpv())
+ if status is None: # we haven't changed it in any way
+ if self._status and testArch+" keyword" in self._status:
+ return True
+ return False
+ else:
+ return status
+
+ def is_masked (self):
+ status = flags.new_masking_status(self.get_cpv())
+ if status != None: # we have locally changed it
+ if status == "masked": return True
+ elif status == "unmasked": return False
+ else:
+ debug("BUG in flags.new_masking_status. It returns",status)
+ else: # we have not touched the status
+ if self._status and ("profile" in self._status or "package.mask" in self._status):
+ return True
+ return False
+
+ def get_all_use_flags (self, installed = False):
+ if installed or not self.is_in_system():
+ tree = self._settings.vartree
+ else:
+ tree = self._settings.porttree
+
+ return list(set(self.get_env_var("IUSE", tree = tree).split()).difference(self.forced_flags))
+
+ def get_matched_dep_packages (self, depvar):
+ # change the useflags, because we have internally changed some, but not made them visible for portage
+ newUseFlags = self.get_new_use_flags()
+ actual = self.get_settings("USE").split()
+ if newUseFlags:
+ for u in newUseFlags:
+ if u[0] == "-" and flags.invert_use_flag(u) in actual:
+ actual.remove(flags.invert_use_flag(u))
+ elif u not in actual:
+ actual.append(u)
+
+ depstring = ""
+ for d in depvar:
+ depstring += self.get_env_var(d)+" "
+
+ portage_dep._dep_check_strict = False
+ deps = portage.dep_check(depstring, None, self._settings.settings, myuse = actual, trees = self._trees)
+ portage_dep._dep_check_strict = True
+
+ if not deps: # FIXME: what is the difference to [1, []] ?
+ return []
+
+ if deps[0] == 0: # error
+ raise DependencyCalcError, deps[1]
+
+ deps = deps[1]
+
+ retlist = []
+
+ for d in deps:
+ if not d[0] == "!":
+ retlist.append(d)
+
+ return retlist
+
+ def get_dep_packages (self, depvar = ["RDEPEND", "PDEPEND", "DEPEND"]):
+ dep_pkgs = [] # the package list
+
+ # change the useflags, because we have internally changed some, but not made them visible for portage
+ newUseFlags = self.get_new_use_flags()
+ actual = self.get_settings("USE").split()
+ if newUseFlags:
+ for u in newUseFlags:
+ if u[0] == "-" and flags.invert_use_flag(u) in actual:
+ actual.remove(flags.invert_use_flag(u))
+ elif u not in actual:
+ actual.append(u)
+
+ depstring = ""
+ for d in depvar:
+ depstring += self.get_env_var(d)+" "
+
+ # let portage do the main stuff ;)
+ # pay attention to any changes here
+ deps = portage.dep_check (depstring, self._settings.vartree.dbapi, self._settings.settings, myuse = actual, trees = self._trees)
+
+ if not deps: # FIXME: what is the difference to [1, []] ?
+ return []
+
+ if deps[0] == 0: # error
+ raise DependencyCalcError, deps[1]
+
+ deps = deps[1]
+
+ for dep in deps:
+ if dep[0] == '!': # blocking sth
+ dep = dep[1:]
+ if dep != self.get_cp(): # not cpv, because a version might explicitly block another one
+ blocked = system.find_installed_packages(dep)
+ if blocked != []:
+ raise BlockedException, (self.get_cpv(), blocked[0].get_cpv())
+ continue # finished with the blocking one -> next
+
+ pkg = system.find_best_match(dep)
+ if not pkg: # try to find masked ones
+ list = system.find_packages(dep, masked = True)
+ if not list:
+ raise PackageNotFoundException, dep
+
+ list = system.sort_package_list(list)
+ done = False
+ for i in range(len(list)-1,0,-1):
+ p = list[i]
+ if not p.is_masked():
+ dep_pkgs.append(p.get_cpv())
+ done = True
+ break
+ if not done:
+ dep_pkgs.append(list[-1].get_cpv())
+ else:
+ dep_pkgs.append(pkg.get_cpv())
+
+ return dep_pkgs
+
+ def get_settings(self, key):
+ self._settingslock.acquire()
+ self._settings.settings.setcpv(self._cpv)
+ v = self._settings.settings[key]
+ self._settingslock.release()
+ return v
+
+ def get_ebuild_path(self):
+ return self._settings.porttree.dbapi.findname(self._cpv)
+
+ def get_env_var(self, var, tree = None):
+ if not tree:
+ mytree = self._settings.vartree
+ if not self.is_installed():
+ mytree = self._settings.porttree
+ else:
+ mytree = tree
+ r = mytree.dbapi.aux_get(self._cpv,[var])
+
+ return r[0]
+
+ def get_use_flags(self):
+ if self.is_installed():
+ return self.get_env_var("USE", tree = self._settings.vartree)
+ else: return ""
+
+ def compare_version(self,other):
+ 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])
+ # Compare versions
+ else:
+ return portage.pkgcmp(v1[1:],v2[1:])
+
+ def matches (self, criterion):
+ if portage.match_from_list(criterion, [self.get_cpv()]) == []:
+ return False
+ else:
+ return True
diff --git a/portato/backend/portage/settings.py b/portato/backend/portage/settings.py
new file mode 100644
index 0000000..5d3aef0
--- /dev/null
+++ b/portato/backend/portage/settings.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+#
+# File: portato/backend/portage/settings.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2006-2007 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+import os
+import portage
+from threading import Lock
+
+class PortageSettings:
+ """Encapsulation of the portage settings.
+
+ @ivar settings: portage settings
+ @ivar settingslock: a simple Lock
+ @ivar trees: a dictionary of the trees
+ @ivar porttree: shortcut to C{trees[root]["porttree"]}
+ @ivar vartree: shortcut to C{trees[root]["vartree"]}
+ @ivar virtuals: shortcut to C{trees[root]["virtuals"]}"""
+
+ def __init__ (self):
+ """Initializes the instance. Calls L{load()}."""
+ self.settingslock = Lock()
+ self.load()
+
+ def load(self):
+ """(Re)loads the portage settings and sets the variables."""
+
+ kwargs = {}
+ for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
+ kwargs[k] = os.environ.get(envvar, None)
+ self.trees = portage.create_trees(trees=None, **kwargs)
+
+ self.settings = self.trees["/"]["vartree"].settings
+
+ for myroot in self.trees:
+ if myroot != "/":
+ self.settings = self.trees[myroot]["vartree"].settings
+ break
+
+ self.settings.unlock()
+
+ root = self.settings["ROOT"]
+
+ self.porttree = self.trees[root]["porttree"]
+ self.vartree = self.trees[root]["vartree"]
+ self.virtuals = self.trees[root]["virtuals"]
+
+ portage.settings = None # we use our own one ...
diff --git a/portato/backend/portage/system.py b/portato/backend/portage/system.py
new file mode 100644
index 0000000..1cfda62
--- /dev/null
+++ b/portato/backend/portage/system.py
@@ -0,0 +1,370 @@
+# -*- coding: utf-8 -*-
+#
+# File: portato/backend/portage/system.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2006-2007 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+import re, os
+import types
+import portage
+
+import package
+from settings import PortageSettings
+from portato.helper import debug, unique_array
+from portato.backend.system_interface import SystemInterface
+
+class PortageSystem (SystemInterface):
+
+ def __init__ (self):
+
+ self.settings = PortageSettings()
+ portage.WORLD_FILE = self.settings.settings["ROOT"]+portage.WORLD_FILE
+
+ def new_package (self, cpv):
+ return package.PortagePackage(cpv)
+
+ def get_config_path (self):
+ return portage.USER_CONFIG_PATH
+
+ def get_world_file_path (self):
+ return portage.WORLD_FILE
+
+ def get_merge_command (self):
+ return ["/usr/bin/python", "/usr/bin/emerge"]
+
+ def get_sync_command (self):
+ return self.get_merge_command()+["--sync"]
+
+ def get_oneshot_option (self):
+ return ["--oneshot"]
+
+ def get_newuse_option (self):
+ return ["--newuse"]
+
+ def get_deep_option (self):
+ return ["--deep"]
+
+ def get_update_option (self):
+ return ["--update"]
+
+ def get_pretend_option (self):
+ return ["--pretend", "--verbose"]
+
+ def get_unmerge_option (self):
+ return ["--unmerge"]
+
+ def find_lambda (self, name):
+ """Returns the function needed by all the find_all_*-functions. Returns None if no name is given.
+
+ @param name: name to build the function of
+ @type name: string
+ @returns:
+ 1. None if no name is given
+ 2. a lambda function
+ @rtype: function"""
+
+ if name != None:
+ return lambda x: re.match(".*"+name+".*",x)
+ else:
+ return lambda x: True
+
+ def geneticize_list (self, list_of_packages):
+ """Convertes a list of cpv's into L{backend.Package}s.
+
+ @param list_of_packages: the list of packages
+ @type list_of_packages: list of gentoolkit.Packages
+ @returns: converted list
+ @rtype: PortagePackage[]"""
+
+ return [package.PortagePackage(x) for x in list_of_packages]
+
+ def find_best (self, list):
+ return package.PortagePackage(portage.best(list))
+
+ def find_best_match (self, search_key, only_installed = False):
+ t = None
+ if not only_installed:
+ t = self.settings.porttree.dep_bestmatch(search_key)
+ else:
+ t = self.settings.vartree.dep_bestmatch(search_key)
+ if t:
+ return package.PortagePackage(t)
+ return None
+
+ def find_packages (self, search_key, masked=False):
+ try:
+ if masked:
+ t = self.settings.porttree.dbapi.xmatch("match-all", search_key)
+ t += self.settings.vartree.dbapi.match(search_key)
+ else:
+ t = self.settings.porttree.dbapi.match(search_key)
+ t += self.settings.vartree.dbapi.match(search_key)
+ # catch the "ambigous package" Exception
+ except ValueError, e:
+ if type(e[0]) == types.ListType:
+ t = []
+ for cp in e[0]:
+ if masked:
+ t += self.settings.porttree.dbapi.xmatch("match-all", cp)
+ t += self.settings.vartree.dbapi.match(cp)
+ else:
+ t += self.settings.porttree.dbapi.match(cp)
+ t += self.settings.vartree.dbapi.match(cp)
+ else:
+ raise ValueError(e)
+ # Make the list of packages unique
+ t = unique_array(t)
+ t.sort()
+ return self.geneticize_list(t)
+
+ def find_installed_packages (self, search_key, masked = False):
+ try:
+ t = self.settings.vartree.dbapi.match(search_key)
+ # catch the "ambigous package" Exception
+ except ValueError, e:
+ if type(e[0]) == types.ListType:
+ t = []
+ for cp in e[0]:
+ t += self.settings.vartree.dbapi.match(cp)
+ else:
+ raise ValueError(e)
+
+ return self.geneticize_list(t)
+
+ def __find_resolved_unresolved (self, list, check):
+ resolved = []
+ unresolved = []
+ for x in list:
+ cpv = x.strip()
+ if len(cpv) and check(cpv):
+ pkg = self.find_best_match(cpv)
+ if pkg:
+ resolved.append(pkg)
+ else:
+ unresolved.append(cpv)
+ return (resolved, self.geneticize_list(unresolved))
+
+ def find_system_packages (self):
+ pkglist = self.settings.settings.packages
+
+ return self.__find_resolved_unresolved(pkglist, lambda cpv: cpv[0] == "*")
+
+ def find_world_packages (self):
+ f = open(portage.WORLD_FILE)
+ pkglist = f.readlines()
+ f.close()
+
+ return self.__find_resolved_unresolved(pkglist, lambda cpv: cpv[0] != "#")
+
+ def find_all_installed_packages (self, name = None, withVersion=True):
+ if withVersion:
+ t = self.settings.vartree.dbapi.cpv_all()
+ if name:
+ t = filter(self.find_lambda(name),t)
+ return self.geneticize_list(t)
+
+ else:
+ t = self.settings.vartree.dbapi.cp_all()
+ if name:
+ t = filter(self.find_lambda(name),t)
+ return t
+
+ def find_all_uninstalled_packages (self, name = None):
+ alist = self.find_all_packages(name)
+ return self.geneticize_list([x for x in alist if not x.is_installed()])
+
+ def find_all_packages (self, name = None, withVersion = True):
+ t = self.settings.porttree.dbapi.cp_all()
+ t += self.settings.vartree.dbapi.cp_all()
+ if name:
+ t = filter(self.find_lambda(name),t)
+ t = unique_array(t)
+
+ if (withVersion):
+ t2 = []
+ for x in t:
+ t2 += self.settings.porttree.dbapi.cp_list(x)
+ t2 += self.settings.vartree.dbapi.cp_list(x)
+ t2 = unique_array(t2)
+ return self.geneticize_list(t2)
+ else:
+ return t;
+
+ def find_all_world_packages (self, name = None):
+ world = filter(self.find_lambda(name), [x.get_cpv() for x in self.find_world_packages()[0]])
+ world = unique_array(world)
+ return self.geneticize_list(world)
+
+ def find_all_system_packages (self, name = None):
+ sys = filter(self.find_lambda(name), [x.get_cpv() for x in self.find_system_packages()[0]])
+ sys = unique_array(sys)
+ return self.geneticize_list(sys)
+
+ def list_categories (self, name = None):
+ categories = self.settings.settings.categories
+ return filter(self.find_lambda(name), categories)
+
+ def split_cpv (self, cpv):
+ cpv = portage.dep_getcpv(cpv)
+ return portage.catpkgsplit(cpv)
+
+ def sort_package_list(self, pkglist):
+ pkglist.sort(package.PortagePackage.compare_version)
+ return pkglist
+
+ def reload_settings (self):
+ self.settings.load()
+
+ def update_world (self, newuse = False, deep = False):
+ # read world file
+ world = open(portage.WORLD_FILE)
+ packages = []
+ for line in world:
+ line = line.strip()
+ if len(line) == 0: continue # empty line
+ if line[0] == "#": continue # comment
+ packages.append(line)
+ world.close()
+
+ # append system packages
+ packages.extend(unique_array([p.get_cp() for p in self.find_all_system_packages()]))
+
+ def get_new_packages (packages):
+ new_packages = []
+ for p in packages:
+ inst = self.find_installed_packages(p)
+ if len(inst) > 1:
+ myslots = set()
+ for i in inst: # get the slots of the installed packages
+ myslots.add(i.get_env_var("SLOT"))
+
+ myslots.add(self.find_best_match(p).get_env_var("SLOT")) # add the slot of the best package in portage
+ for slot in myslots:
+ new_packages.append(\
+ self.find_best(\
+ [x.get_cpv() for x in self.find_packages("%s:%s" % (i.get_cp(), slot))]\
+ ))
+ else:
+ new_packages.append(self.find_best_match(p))
+
+ return new_packages
+
+ checked = []
+ updating = []
+ raw_checked = []
+ def check (p, add_not_installed = True):
+ """Checks whether a package is updated or not."""
+ if p.get_cp() in checked: return
+ else: checked.append(p.get_cp())
+
+ appended = False
+ tempDeep = False
+
+ if not p.is_installed():
+ oldList = self.find_installed_packages(p.get_slot_cp())
+ if oldList:
+ old = oldList[0] # we should only have one package here - else it is a bug
+ else:
+ oldList = self.sort_package_list(self.find_installed_packages(p.get_cp()))
+ if not oldList:
+ if add_not_installed:
+ debug("Not found installed",p.get_cpv(),"==> adding")
+ oldList = [p]
+ else:
+ return
+ old = oldList[-1]
+
+ updating.append((p, old))
+ appended = True
+ p = old
+
+ if newuse and p.is_installed() and p.is_in_system(): # there is no use to check newuse for a package which is not existing in portage anymore :)
+
+ new_iuse = set(p.get_all_use_flags(installed = False)) # IUSE in the ebuild
+ old_iuse = set(p.get_all_use_flags(installed = True)) # IUSE in the vardb
+
+ if new_iuse.symmetric_difference(old_iuse): # difference between new_iuse and old_iuse
+ tempDeep = True
+ if not appended:
+ updating.append((p,p))
+ appended = True
+
+ else:
+ old = set(p.get_installed_use_flags())
+ new = set(p.get_settings("USE").split())
+
+ if new_iuse.intersection(new) != old_iuse.intersection(old):
+ tempDeep = True
+ if not appended:
+ updating.append((p,p))
+ appended = True
+
+ if deep or tempDeep:
+ states = [(["RDEPEND","PDEPEND"],True), (["DEPEND"], False)]
+
+ for state in states:
+ for i in p.get_matched_dep_packages(state[0]):
+ if i not in raw_checked:
+ raw_checked.append(i)
+ bm = get_new_packages([i])
+ if not bm:
+ debug("Bug? No best match could be found:",i)
+ else:
+ for pkg in bm:
+ if not pkg: continue
+ check(pkg, state[1])
+
+ for p in get_new_packages(packages):
+ if not p: continue # if a masked package is installed we have "None" here
+ check(p, True)
+
+ return updating
+
+ use_descs = {}
+ local_use_descs = {}
+ def get_use_desc (self, flag, package = None):
+ # In the first run the dictionaries 'use_descs' and 'local_use_descs' are filled.
+
+ # fill cache if needed
+ if self.use_descs == {} or self.local_use_descs == {}:
+ # read use.desc
+ fd = open(self.settings.settings["PORTDIR"]+"/profiles/use.desc")
+ lines = fd.readlines()
+ fd.close()
+ for line in lines:
+ line = line.strip()
+ if line != "" and line[0] != '#':
+ fields = [x.strip() for x in line.split(" - ",1)]
+ if len(fields) == 2:
+ self.use_descs[fields[0]] = fields[1]
+
+ # read use.local.desc
+ fd = open(self.settings.settings["PORTDIR"]+"/profiles/use.local.desc")
+ lines = fd.readlines()
+ fd.close()
+ for line in lines:
+ line = line.strip()
+ if line != "" and line[0] != '#':
+ fields = [x.strip() for x in line.split(":",1)]
+ if len(fields) == 2:
+ if not fields[0] in self.local_use_descs: # create
+ self.local_use_descs[fields[0]] = {}
+ subfields = [x.strip() for x in fields[1].split(" - ",1)]
+ if len(subfields) == 2:
+ self.local_use_descs[fields[0]][subfields[0]] = subfields[1]
+
+ # start
+ desc = None
+ if flag in self.use_descs:
+ desc = self.use_descs[flag]
+ if package != None:
+ if package in self.local_use_descs:
+ if flag in self.local_use_descs[package]:
+ desc = self.local_use_descs[package][flag]
+ return desc
diff --git a/portato/backend/portage_helper.py b/portato/backend/portage_helper.py
deleted file mode 100644
index be4c76c..0000000
--- a/portato/backend/portage_helper.py
+++ /dev/null
@@ -1,467 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# File: portato/backend/portage_helper.py
-# This file is part of the Portato-Project, a graphical portage-frontend.
-#
-# Copyright (C) 2006-2007 René 'Necoro' Neumann
-# This is free software. You may redistribute copies of it under the terms of
-# the GNU General Public License version 2.
-# There is NO WARRANTY, to the extent permitted by law.
-#
-# Written by René 'Necoro' Neumann <necoro@necoro.net>
-
-import re, os
-import types
-import portage
-
-from portage_util import unique_array
-
-from portato.backend import portage_settings
-import package
-
-from portato.helper import debug
-
-def find_lambda (name):
- """Returns the function needed by all the find_all_*-functions. Returns None if no name is given.
-
- @param name: name to build the function of
- @type name: string
- @returns:
- 1. None if no name is given
- 2. a lambda function
- @rtype: function"""
-
- if name != None:
- return lambda x: re.match(".*"+name+".*",x)
- else:
- return lambda x: True
-
-def geneticize_list (list_of_packages):
- """Convertes a list of cpv's into L{backend.Package}s.
-
- @param list_of_packages: the list of packages
- @type list_of_packages: list of gentoolkit.Packages
- @returns: converted list
- @rtype: backend.Package[]"""
-
- return [package.Package(x) for x in list_of_packages]
-
-def find_best (list):
- """Returns the best package out of a list of packages.
-
- @param list: the list of packages to select from
- @type list: string[]
- @returns: the best package
- @rtype: backend.Package"""
-
- return package.Package(portage.best(list))
-
-def find_best_match (search_key, only_installed = False):
- """Finds the best match in the portage tree. It does not find masked packages!
-
- @param search_key: the key to find in the portage tree
- @type search_key: string
- @param only_installed: if True, only installed packages are searched
- @type only_installed: boolean
-
- @returns: the package found or None
- @rtype: backend.Package"""
-
- t = None
- if not only_installed:
- t = portage_settings.porttree.dep_bestmatch(search_key)
- else:
- t = portage_settings.vartree.dep_bestmatch(search_key)
- if t:
- return package.Package(t)
- return None
-
-def find_packages (search_key, masked=False):
- """This returns a list of packages which have to fit exactly. Additionally ranges like '<,>,=,~,!' et. al. are possible.
-
- @param search_key: the key to look for
- @type search_key: string
- @param masked: if True, also look for masked packages
- @type masked: boolean
-
- @returns: list of found packages
- @rtype: backend.Package[]"""
-
- try:
- if masked:
- t = portage_settings.porttree.dbapi.xmatch("match-all", search_key)
- t += portage_settings.vartree.dbapi.match(search_key)
- else:
- t = portage_settings.porttree.dbapi.match(search_key)
- t += portage_settings.vartree.dbapi.match(search_key)
- # catch the "ambigous package" Exception
- except ValueError, e:
- if type(e[0]) == types.ListType:
- t = []
- for cp in e[0]:
- if masked:
- t += portage_settings.porttree.dbapi.xmatch("match-all", cp)
- t += portage_settings.vartree.dbapi.match(cp)
- else:
- t += portage_settings.porttree.dbapi.match(cp)
- t += portage_settings.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.
-
- @param search_key: the key to look for
- @type search_key: string
- @param masked: if True, also look for masked packages
- @type masked: boolean
-
- @returns: list of found packages
- @rtype: backend.Package[]"""
-
- try:
- t = portage_settings.vartree.dbapi.match(search_key)
- # catch the "ambigous package" Exception
- except ValueError, e:
- if type(e[0]) == types.ListType:
- t = []
- for cp in e[0]:
- t += portage_settings.vartree.dbapi.match(cp)
- else:
- raise ValueError(e)
-
- return geneticize_list(t)
-
-def find_system_packages ():
- """Looks for all packages saved as "system-packages".
-
- @returns: a tuple of (resolved_packages, unresolved_packages).
- @rtype: (backend.Package[], backend.Package[])"""
-
- pkglist = portage_settings.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 (resolved, geneticize_list(unresolved))
-
-def find_world_packages ():
- """Looks for all packages saved in the world-file.
-
- @returns: a tuple of (resolved_packages, unresolved_packages).
- @rtype: (backend.Package[], backend.Package[])"""
-
- 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 (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.
-
- @param name: the name to look for - it is expanded to .*name.* ; if None, all packages are returned
- @type name: string or None
- @param withVersion: if True version-specific packages are returned; else only the cat/package-strings a delivered
- @type withVersion: boolean
-
- @returns: all packages/cp-strings found
- @rtype: backend.Package[] or cp-string[]"""
-
- if withVersion:
- t = portage_settings.vartree.dbapi.cpv_all()
- if name:
- t = filter(find_lambda(name),t)
- return geneticize_list(t)
-
- else:
- t = portage_settings.vartree.dbapi.cp_all()
- if name:
- t = filter(find_lambda(name),t)
- return t
-
-def find_all_uninstalled_packages (name=None):
- """Finds all uninstalled packages matching a name or all if no name is specified.
-
- @param name: the name to look for - it is expanded to .*name.* ; if None, all packages are returned
- @type name: string or None
- @returns: all packages found
- @rtype: backend.Package[]"""
-
- 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.
-
- @param name: the name to look for - it is expanded to .*name.* ; if None, all packages are returned
- @type name: string or None
- @param withVersion: if True version-specific packages are returned; else only the cat/package-strings a delivered
- @type withVersion: boolean
-
- @returns: all packages/cp-strings found
- @rtype: backend.Package[] or cp-string[]"""
-
- t = portage_settings.porttree.dbapi.cp_all()
- t += portage_settings.vartree.dbapi.cp_all()
- if name:
- t = filter(find_lambda(name),t)
- t = unique_array(t)
-
- if (withVersion):
- t2 = []
- for x in t:
- t2 += portage_settings.porttree.dbapi.cp_list(x)
- t2 += portage_settings.vartree.dbapi.cp_list(x)
- t2 = unique_array(t2)
- return geneticize_list(t2)
- else:
- return t;
-
-def find_all_world_packages (name=None):
- """Finds all world packages matching a name or all if no name is specified.
-
- @param name: the name to look for - it is expanded to .*name.* ; if None, all packages are returned
- @type name: string or None
- @returns: all packages found
- @rtype: backend.Package[]"""
-
- world = filter(find_lambda(name), [x.get_cpv() for x in find_world_packages()[0]])
- world = unique_array(world)
- return geneticize_list(world)
-
-def find_all_system_packages (name=None):
- """Finds all system packages matching a name or all if no name is specified.
-
- @param name: the name to look for - it is expanded to .*name.* ; if None, all packages are returned
- @type name: string or None
- @returns: all packages found
- @rtype: backend.Package[]"""
-
- sys = filter(find_lambda(name), [x.get_cpv() for x in find_system_packages()[0]])
- sys = unique_array(sys)
- return geneticize_list(sys)
-
-def list_categories (name=None):
- """Finds all categories matching a name or all if no name is specified.
-
- @param name: the name to look for - it is expanded to .*name.* ; if None, all categories are returned
- @type name: string or None
- @returns: all categories found
- @rtype: string[]"""
-
- categories = portage_settings.settings.categories
- return filter(find_lambda(name), categories)
-
-def split_package_name (name):
- """Splits a package name in its elements.
-
- @param name: name to split
- @type name: string
- @returns: list: [category, name, version, rev] whereby rev is "r0" if not specified in the name
- @rtype: string[]"""
-
- r = portage.catpkgsplit(portage.dep_getcpv(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[]"""
-
- pkglist.sort(package.Package.compare_version)
- return pkglist
-
-def reload_settings ():
- """Reloads portage."""
- portage_settings.load()
-
-def update_world (newuse = False, deep = False):
- """Calculates the packages to get updated in an update world.
-
- @param newuse: Checks if a use-flag has a different state then to install time.
- @type newuse: boolean
- @param deep: Not only check world packages but also there dependencies.
- @type deep: boolean
- @returns: a list containing of the tuple (new_package, old_package)
- @rtype: (backend.Package, backend.Package)[]"""
-
- # read world file
- world = open(portage.WORLD_FILE)
- packages = []
- for line in world:
- line = line.strip()
- if len(line) == 0: continue # empty line
- if line[0] == "#": continue # comment
- packages.append(line)
- world.close()
-
- # append system packages
- packages.extend(unique_array([p.get_cp() for p in find_all_system_packages()]))
-
- def get_new_packages (packages):
- new_packages = []
- for p in packages:
- inst = find_installed_packages(p)
- if len(inst) > 1:
- myslots = set()
- for i in inst: # get the slots of the installed packages
- myslots.add(i.get_env_var("SLOT"))
-
- myslots.add(find_best_match(p).get_env_var("SLOT")) # add the slot of the best package in portage
- for slot in myslots:
- new_packages.append(\
- find_best(\
- [x.get_cpv() for x in find_packages("%s:%s" % (i.get_cp(), slot))]\
- ))
- else:
- new_packages.append(find_best_match(p))
-
- return new_packages
-
- checked = []
- updating = []
- raw_checked = []
- def check (p, add_not_installed = True):
- """Checks whether a package is updated or not."""
- if p.get_cp() in checked: return
- else: checked.append(p.get_cp())
-
- appended = False
- tempDeep = False
-
- if not p.is_installed():
- oldList = find_installed_packages(p.get_slot_cp())
- if oldList:
- old = oldList[0] # we should only have one package here - else it is a bug