# -*- coding: utf-8 -*- # # File: portato/backend/portage_helper.py # This file is part of the Portato-Project, a graphical portage-frontend. # # Copyright (C) 2006 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 import re, os, copy import portage, gentoolkit from portage_util import unique_array from portato.backend import * 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 gentoolkit.Packages 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_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 = porttree.dep_bestmatch(search_key) else: t = 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[]""" return geneticize_list(gentoolkit.find_packages(search_key, masked)) 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[]""" return geneticize_list(gentoolkit.find_installed_packages(search_key, masked)) 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[])""" list = gentoolkit.find_system_packages() return (geneticize_list(list[0]), geneticize_list(list[1])) 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[])""" list = gentoolkit.find_world_packages() return geneticize_list(list[0]),geneticize_list(list[1]) 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: return geneticize_list(gentoolkit.find_all_installed_packages(find_lambda(name))) else: t = 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[]""" return geneticize_list(gentoolkit.find_all_uninstalled_packages(find_lambda(name))) 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[]""" if (withVersion): return geneticize_list(gentoolkit.find_all_packages(find_lambda(name))) 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 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 get_all_versions (cp): """Returns all versions of a certain package. @param cp: the package @type cp: string (cat/pkg) @returns: the list of found packages @rtype: backend.Package[]""" t = porttree.dbapi.cp_list(cp) t += vartree.dbapi.cp_list(cp) t = unique_array(t) return geneticize_list(t) def get_all_installed_versions (cp): """Returns all installed versions of a certain package. @param cp: the package @type cp: string (cat/pkg) @returns: the list of found packages @rtype: backend.Package[]""" return geneticize_list(vartree.dbapi.cp_list(cp)) 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 = gentoolkit.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[]""" return gentoolkit.split_package_name(name) 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) def reload_settings (): """Reloads portage.""" gentoolkit.settings = portage.config(config_incrementals = copy.deepcopy(gentoolkit.settings.incrementals)) 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 not len(line): continue # empty line if line[0] == "#": continue packages.append(line) world.close() sys = gentoolkit.settings.packages for x in sys: if x[0] == "*": x = x[1:] packages.append(x.strip()) # 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)): mykey = portage.dep_getkey(expanded_atom) if mykey in gentoolkit.settings.pprovideddict and portage.match_from_list(expanded_atom, settings.pprovideddict[mykey]): packages.remove(atom) break packages = [find_best_match(x) for x in packages] checked = [] updating = [] raw_checked = [] def check (p): """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_cp()) if oldList: old = oldList[0] # assume we have only one there; FIXME: slotted packages else: debug("Bug? Not found installed one:",p.get_cp()) return updating.append((p, old)) appended = True p = old if newuse: old = p.get_installed_use_flags() new = p.get_settings("USE").split() for u in p.get_all_use_flags(): if (u in new) != (u in old): if not appended: updating.append((p,p)) tempDeep = True if deep or tempDeep: for i in p.get_matched_dep_packages(): if i not in raw_checked: raw_checked.append(i) bm = find_best_match(i) if not bm: debug("Bug? No best match could be found:",i) else: check(bm) for p in packages: if not p: continue # if a masked package is installed we have "None" here check(p) return updating use_descs = {} local_use_descs = {} def get_use_desc (flag, package = None): """Returns the description of a specific useflag or None if no desc was found. If a package is given (in the / format) the local use descriptions are searched too. @param flag: flag to get the description for @type flag: string @param package: name of a package: if given local use descriptions are searched too @type package: cp-string @returns: found description @rtype: string""" # In the first run the dictionaries 'use_descs' and 'local_use_descs' are filled. # fill cache if needed if use_descs == {} or local_use_descs == {}: # read use.desc fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.desc") for line in fd.readlines(): line = line.strip() if line != "" and line[0] != '#': fields = [x.strip() for x in line.split(" - ",1)] if len(fields) == 2: use_descs[fields[0]] = fields[1] # read use.local.desc fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.local.desc") for line in fd.readlines(): 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 local_use_descs: # create local_use_descs[fields[0]] = {} subfields = [x.strip() for x in fields[1].split(" - ",1)] if len(subfields) == 2: local_use_descs[fields[0]][subfields[0]] = subfields[1] # start desc = None if flag in use_descs: desc = use_descs[flag] if package != None: if package in local_use_descs: if flag in local_use_descs[package]: desc = local_use_descs[package][flag] return desc