From c7993113d10ec8412cf60663d3afcbb9643fbb2a Mon Sep 17 00:00:00 2001 From: necoro <> Date: Wed, 6 Sep 2006 19:11:50 +0000 Subject: --- geneticone/package.py | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 geneticone/package.py (limited to 'geneticone/package.py') diff --git a/geneticone/package.py b/geneticone/package.py new file mode 100644 index 0000000..6ec2299 --- /dev/null +++ b/geneticone/package.py @@ -0,0 +1,202 @@ +#!/usr/bin/python + +from geneticone import * + +import gentoolkit +import portage +from portage_util import unique_array + +class Package (gentoolkit.Package): + """This is just a subclass of the Package-class of gentoolkit.""" + + def __init__ (self, cpv): + gentoolkit.Package.__init__(self, cpv) + + def get_mask_status(self): + '''gets the numeric mask status of a package + can be translated as string: + maskmodes = [ " ", " ~", " -", "M ", "M~", "M-" ] + (0=unmasked 1=~arch 2=-arch etc.) + + This method adapted from equery 0.1.4 + Original author: Karl Trygve Kalleberg + ''' + + pkgmask = 0 + if self.is_masked(): + pkgmask = pkgmask + 3 + keywords = self.get_env_var("KEYWORDS").split() + if "~" + gentoolkit.settings["ARCH"] in keywords: + pkgmask = pkgmask + 1 + elif "-*" in keywords or "-" + gentoolkit.settings["ARCH"] in keywords: + pkgmask = pkgmask + 2 + return pkgmask + + def get_size (self): + return self.size() + + def get_all_useflags (self): + """Returns a list of _all_ useflags for this package.""" + return self.get_env_var("IUSE").split() + + def get_all_deps (self): + """Returns a linearised list of all first-level dependencies for this package, on + the form [(comparator, [use flags], cpv), ...]""" + return unique_array(self.get_compiletime_deps()+self.get_runtime_deps()+self.get_postmerge_deps()) + + def get_dep_packages (self): + """Returns a cpv-list of packages on which this package depends and which have not been installed yet. + raises: BlockedException, PackageNotFoundException.""" + dep_pkgs = [] # the package list + + # let portage do the main stuff ;) + # pay attention to any changes here + deps = portage.dep_check (self.get_env_var("RDEPEND")+" "+self.get_env_var("DEPEND"), vartree.dbapi, self._settings) + + if not deps: # what is the difference to [1, []] ? + return [] + + deps = deps[1] + + for dep in deps: + if dep[0] == '!': + blocked = find_installed_packages(dep[1:]) + if blocked != []: + raise BlockedException, blocked[0].get_cpv() + else: # next flag + continue + + pkg = find_best_match(dep) + if not dep: + raise PackageNotFoundException, dep + else: + dep_pkgs.append(pkg.get_cpv()) + + return dep_pkgs + + def own_get_dep_packages (self, old_cpv_dict = {}): + # XXX: after having finished this, i realized, that there is already a portage function -.- ; + # will keep this in case portage changes anything + """Returns a list of all packages (i.e. package-cpvs) which this package depends on and which not have been installed yet. + Param old_cpv_dict is a {cp: version}-dictionary holding already found deps. + Raises a BlockedException if the package is being blocked by another installed package.""" + # XXX: This won't find blocking dependencies + # XXX: Has some problems with modular X (this has a very strange ebuild) ... we should enhance _parse_deps + print "Actual: "+self._cpv # debug output + + uses = [] # list of actual useflags / useflags the package has been installed with + dep_packages = [] # list of packages returned + dep_cpv_dict = {} # all dependencies are inserted here + + # get useflags + if self.is_installed(): + uses = self.get_set_useflags() + else: + uses = self.get_settings("USE") + + # cycle through dependencies + for (comp, flags, dep_cpv) in self.get_all_deps(): + + # find blocking packages + if comp and comp[0] == '!': + blocked = find_installed_packages(comp[1:]+dep_cpv) + if blocked != []: + raise BlockedException, blocked[0].get_cpv() + else: # next flag + continue + + # look whether this package is really required + needDep = True + for flag in flags: + if (flag[0] == '!' and flag[1:] in uses) or (flag[0] != '!' and flag not in uses): + needDep = False + break + + if needDep: # it is ... + if find_installed_packages(comp+dep_cpv) == []: # ... and not installed yet + d = find_best_match(comp+dep_cpv) + if not d: # no package found + raise PackageNotFoundException, dep_cpv + if d.get_cp() not in old_cpv_dict: # ... and not found already by an other package + dep_cpv_dict[d.get_cp()] = d.get_version() + print "Dep: "+d.get_cpv() # debug + dep_packages.append(d.get_cpv()) + + for dep in dep_packages: # find dependencies for each package + old_cpv_dict.update(dep_cpv_dict) + old_cpv_dict.update({self.get_cp() : self.get_version()}) + dep_packages += find_packages("="+dep)[0].own_get_dep_packages(old_cpv_dict) + + return unique_array(dep_packages) + + def get_set_useflags (self): + """Returns a list of the useflags enabled at installation time. If package is not installed, it returns an empty list.""" + if self.is_installed(): + uses = self.get_use_flags().split() + iuses = self.get_all_useflags() + set = [] + for u in iuses: + if u in uses: + set.append(u) + return set + else: + return [] + + def get_cp (self): + """Returns category/package.""" + return self.get_category()+"/"+self.get_name() + + def is_masked (self): + """Returns True if either masked by package.mask or by profile.""" + # XXX: Better solution than string comparison? + status = portage.getmaskingstatus(self._cpv) + if "profile" in status or "package.mask" in status: + return True + return False + + def _parse_deps(self,deps,curuse=[],level=0): + """Modified method "_parse_deps" of gentoolkit.Package. + Do NOT ignore blocks.""" + # store (comparator, [use predicates], cpv) + r = [] + comparators = ["~","<",">","=","<=",">="] + end = len(deps) + i = 0 + while i < end: + blocked = False + tok = deps[i] + if tok == ')': + return r,i + if tok[-1] == "?": + tok = tok.replace("?","") + sr,l = self._parse_deps(deps[i+2:],curuse=curuse+[tok],level=level+1) + r += sr + i += l + 3 + continue + if tok == "||": + sr,l = self._parse_deps(deps[i+2:],curuse,level=level+1) + r += sr + i += l + 3 + continue + # conjonction, like in "|| ( ( foo bar ) baz )" => recurse + if tok == "(": + sr,l = self._parse_deps(deps[i+1:],curuse,level=level+1) + r += sr + i += l + 2 + continue + # pkg block "!foo/bar" => ignore it + if tok[0] == "!": + #i += 1 + #continue + blocked = True # added + tok = tok[1:] # added + # pick out comparator, if any + cmp = "" + for c in comparators: + if tok.find(c) == 0: + cmp = c + if blocked: cmp = "!"+cmp # added + tok = tok[len(cmp):] + r.append((cmp,curuse,tok)) + i += 1 + return r,i -- cgit v1.2.3-70-g09d2