summaryrefslogtreecommitdiff
path: root/portato/backend
diff options
context:
space:
mode:
Diffstat (limited to 'portato/backend')
-rw-r--r--portato/backend/__init__.py64
-rw-r--r--portato/backend/exceptions.py16
-rw-r--r--portato/backend/flags.py1308
-rw-r--r--portato/backend/package.py786
-rw-r--r--portato/backend/portage/__init__.py8
-rw-r--r--portato/backend/portage/package.py572
-rw-r--r--portato/backend/portage/package_22.py10
-rw-r--r--portato/backend/portage/sets.py168
-rw-r--r--portato/backend/portage/settings.py78
-rw-r--r--portato/backend/portage/settings_22.py12
-rw-r--r--portato/backend/portage/system.py768
-rw-r--r--portato/backend/portage/system_22.py60
-rw-r--r--portato/backend/system_interface.py492
13 files changed, 2171 insertions, 2171 deletions
diff --git a/portato/backend/__init__.py b/portato/backend/__init__.py
index b2a5a43..1f62d6b 100644
--- a/portato/backend/__init__.py
+++ b/portato/backend/__init__.py
@@ -20,52 +20,52 @@ SYSTEM = "portage" # the name of the current system
_sys = None # the SystemInterface-instance
class _Package (object):
- """Wrapping class from which L{portato.backend.Package} inherits. This is used by the flags module to check
- whether an object is a package. It cannot use the normal Package class as this results in cyclic dependencies."""
+ """Wrapping class from which L{portato.backend.Package} inherits. This is used by the flags module to check
+ whether an object is a package. It cannot use the normal Package class as this results in cyclic dependencies."""
- def __init__ (self):
- raise TypeError, "Calling __init__ on portato.backend._Package objects is not allowed."
+ def __init__ (self):
+ raise TypeError, "Calling __init__ on portato.backend._Package objects is not allowed."
class SystemWrapper (SystemInterface):
- """This is a wrapper to the different system interfaces, allowing the direct import via C{from portato.backend import system}.
- With this wrapper a change of the system is propagated to all imports."""
-
- def __getattribute__ (self, name):
- """Just pass all attribute accesses directly to _sys."""
- return getattr(_sys, name)
+ """This is a wrapper to the different system interfaces, allowing the direct import via C{from portato.backend import system}.
+ With this wrapper a change of the system is propagated to all imports."""
+
+ def __getattribute__ (self, name):
+ """Just pass all attribute accesses directly to _sys."""
+ return getattr(_sys, name)
def set_system (new_sys):
- """Sets the current system to a new one.
+ """Sets the current system to a new one.
- @param new_sys: the name of the system to take
- @type new_sys: string"""
+ @param new_sys: the name of the system to take
+ @type new_sys: string"""
- global SYSTEM
- if new_sys != SYSTEM:
- SYSTEM = new_sys
- load_system()
+ global SYSTEM
+ if new_sys != SYSTEM:
+ SYSTEM = new_sys
+ load_system()
def load_system ():
- """Loads the current chosen system.
+ """Loads the current chosen system.
- @raises InvalidSystemError: if an inappropriate system is set"""
-
- global _sys
+ @raises InvalidSystemError: if an inappropriate system is set"""
+
+ global _sys
- if SYSTEM == "portage":
- debug("Setting Portage System")
- from .portage import PortageSystem
- _sys = PortageSystem ()
- elif SYSTEM == "catapult":
- debug("Setting Catapult System")
- from .catapult import CatapultSystem
- _sys = CatapultSystem()
- else:
- raise InvalidSystemError, SYSTEM
+ if SYSTEM == "portage":
+ debug("Setting Portage System")
+ from .portage import PortageSystem
+ _sys = PortageSystem ()
+ elif SYSTEM == "catapult":
+ debug("Setting Catapult System")
+ from .catapult import CatapultSystem
+ _sys = CatapultSystem()
+ else:
+ raise InvalidSystemError, SYSTEM
system = SystemWrapper()
def is_package(what):
- return isinstance(what, _Package)
+ return isinstance(what, _Package)
load_system()
diff --git a/portato/backend/exceptions.py b/portato/backend/exceptions.py
index 42f9d44..37e9bda 100644
--- a/portato/backend/exceptions.py
+++ b/portato/backend/exceptions.py
@@ -11,17 +11,17 @@
# Written by René 'Necoro' Neumann <necoro@necoro.net>
class BlockedException (Exception):
- """An exception marking, that some package is blocking another one."""
- pass
+ """An exception marking, that some package is blocking another one."""
+ pass
class PackageNotFoundException (Exception):
- """An exception marking that a package could not be found."""
- pass
+ """An exception marking that a package could not be found."""
+ pass
class DependencyCalcError (Exception):
- """An error occured during dependency calculation."""
- pass
+ """An error occured during dependency calculation."""
+ pass
class InvalidSystemError (Exception):
- """An invalid system is set."""
- pass
+ """An invalid system is set."""
+ pass
diff --git a/portato/backend/flags.py b/portato/backend/flags.py
index b151665..4aa6b8e 100644
--- a/portato/backend/flags.py
+++ b/portato/backend/flags.py
@@ -20,738 +20,738 @@ from . import system, is_package
from ..helper import debug, error, unique_array
CONFIG = {
- "usefile" : "portato",
- "maskfile" : "portato",
- "testingfile" : "portato",
- "usePerVersion" : True,
- "maskPerVersion" : True,
- "testingPerVersion" : True
- }
+ "usefile" : "portato",
+ "maskfile" : "portato",
+ "testingfile" : "portato",
+ "usePerVersion" : True,
+ "maskPerVersion" : True,
+ "testingPerVersion" : True
+ }
class Constants:
- def __init__ (self):
- self.clear()
-
- def clear (self):
- self._use_path = None
- self._mask_path = None
- self._unmask_path = None
- self._testing_path = None
- self._use_path_is_dir = None
- self._mask_path_is_dir = None
- self._unmask_path_is_dir = None
- self._testing_path_is_dir = None
+ def __init__ (self):
+ self.clear()
+
+ def clear (self):
+ self._use_path = None
+ self._mask_path = None
+ self._unmask_path = None
+ self._testing_path = None
+ self._use_path_is_dir = None
+ self._mask_path_is_dir = None
+ self._unmask_path_is_dir = None
+ self._testing_path_is_dir = None
- def __get (self, name, path):
- if self.__dict__[name] is None:
- self.__dict__[name] = os.path.join(system.get_config_path(), path)
+ def __get (self, name, path):
+ if self.__dict__[name] is None:
+ self.__dict__[name] = os.path.join(system.get_config_path(), path)
- return self.__dict__[name]
+ return self.__dict__[name]
- def __is_dir(self, path):
- name = "_" + path + "_is_dir"
- if self.__dict__[name] is None:
- self.__dict__[name] = os.path.isdir(self.__class__.__dict__[path](self))
- return self.__dict__[name]
-
- def use_path (self):
- return self.__get("_use_path", "package.use")
+ def __is_dir(self, path):
+ name = "_" + path + "_is_dir"
+ if self.__dict__[name] is None:
+ self.__dict__[name] = os.path.isdir(self.__class__.__dict__[path](self))
+ return self.__dict__[name]
+
+ def use_path (self):
+ return self.__get("_use_path", "package.use")
- def use_path_is_dir (self):
- return self.__is_dir("use_path")
+ def use_path_is_dir (self):
+ return self.__is_dir("use_path")
- def mask_path (self):
- return self.__get("_mask_path", "package.mask")
+ def mask_path (self):
+ return self.__get("_mask_path", "package.mask")
- def mask_path_is_dir (self):
- return self.__is_dir("mask_path")
+ def mask_path_is_dir (self):
+ return self.__is_dir("mask_path")
- def unmask_path (self):
- return self.__get("_unmask_path", "package.unmask")
+ def unmask_path (self):
+ return self.__get("_unmask_path", "package.unmask")
- def unmask_path_is_dir (self):
- return self.__is_dir("unmask_path")
+ def unmask_path_is_dir (self):
+ return self.__is_dir("unmask_path")
- def testing_path (self):
- return self.__get("_testing_path", "package.keywords")
+ def testing_path (self):
+ return self.__get("_testing_path", "package.keywords")
- def testing_path_is_dir (self):
- return self.__is_dir("testing_path")
+ def testing_path_is_dir (self):
+ return self.__is_dir("testing_path")
CONST = Constants()
### GENERAL PART ###
def grep (pkg, path):
- """Grep runs "egrep" on a given path and looks for occurences of a given package.
- @param pkg: the package
- @type pkg: string (cpv) or L{backend.Package}-object
- @param path: path to look in
- @type path: string
-
- @returns: occurences of pkg in the format: "file:line-no:complete_line_found"
- @rtype: string"""
-
- if not is_package(pkg):
- pkg = system.new_package(pkg) # assume it is a cpv or a gentoolkit.Package
-
- if os.path.exists(path):
- command = "egrep -x -n -r -H '^[<>!=~]{0,2}%s(-[0-9].*)?[[:space:]]?.*$' %s" # %s is replaced in the next line ;)
- return Popen((command % (pkg.get_cp(), path)), shell = True, stdout = PIPE).communicate()[0].splitlines()
- else:
- return []
+ """Grep runs "egrep" on a given path and looks for occurences of a given package.
+ @param pkg: the package
+ @type pkg: string (cpv) or L{backend.Package}-object
+ @param path: path to look in
+ @type path: string
+
+ @returns: occurences of pkg in the format: "file:line-no:complete_line_found"
+ @rtype: string"""
+
+ if not is_package(pkg):
+ pkg = system.new_package(pkg) # assume it is a cpv or a gentoolkit.Package
+
+ if os.path.exists(path):
+ command = "egrep -x -n -r -H '^[<>!=~]{0,2}%s(-[0-9].*)?[[:space:]]?.*$' %s" # %s is replaced in the next line ;)
+ return Popen((command % (pkg.get_cp(), path)), shell = True, stdout = PIPE).communicate()[0].splitlines()
+ else:
+ return []
def get_data(pkg, path):
- """This splits up the data of L{grep} and builds tuples in the format (file,line,criterion,list_of_flags).
- @param pkg: package to find
- @type pkg: string (cpv) or L{backend.Package}-object
- @param path: path to look in
- @type path: string
-
- @returns: a list of tuples in the form (file,line,criterion,list_of_flags)
- @rtype: (string,string,string,string[])[]"""
-
- flags = []
-
- # do grep
- list = grep(pkg, path)
-
- for i in range(len(list)):
- file, line, fl = tuple(list[i].split(":")) # get file, line and flag-list
- fl = fl.split()
- crit = fl[0]
- fl = fl[1:]
- # stop after first comment
- for j in range(len(fl)):
- if fl[j][0] == "#": # comment - stop here
- fl = fl[:j]
- break
- flags.append((file,line,crit,fl))
-
- return flags
+ """This splits up the data of L{grep} and builds tuples in the format (file,line,criterion,list_of_flags).
+ @param pkg: package to find
+ @type pkg: string (cpv) or L{backend.Package}-object
+ @param path: path to look in
+ @type path: string
+
+ @returns: a list of tuples in the form (file,line,criterion,list_of_flags)
+ @rtype: (string,string,string,string[])[]"""
+
+ flags = []
+
+ # do grep
+ list = grep(pkg, path)
+
+ for i in range(len(list)):
+ file, line, fl = tuple(list[i].split(":")) # get file, line and flag-list
+ fl = fl.split()
+ crit = fl[0]
+ fl = fl[1:]
+ # stop after first comment
+ for j in range(len(fl)):
+ if fl[j][0] == "#": # comment - stop here
+ fl = fl[:j]
+ break
+ flags.append((file,line,crit,fl))
+
+ return flags
def set_config (cfg):
- """This function sets the CONFIG-variable for the whole module. Use this instead of modifying L{CONFIG} directly.
- @param cfg: a dictionary with at least all the keys of the CONFIG-var
- @type cfg: dict
- @raises KeyError: if a keyword is missing in the new cfg"""
+ """This function sets the CONFIG-variable for the whole module. Use this instead of modifying L{CONFIG} directly.
+ @param cfg: a dictionary with at least all the keys of the CONFIG-var
+ @type cfg: dict
+ @raises KeyError: if a keyword is missing in the new cfg"""
- for i in CONFIG.keys():
- if not i in cfg:
- raise KeyError, "Missing keyword in config: "+i
+ for i in CONFIG.keys():
+ if not i in cfg:
+ raise KeyError, "Missing keyword in config: "+i
- for i in CONFIG:
- CONFIG[i] = cfg[i]
+ for i in CONFIG:
+ CONFIG[i] = cfg[i]
def generate_path (cpv, exp):
- """Generates the correct path out of given wildcards.
- These wildcards can be:
- - $(cat) : category
- - $(cat-1): first part of the category (e.g. "app")
- - $(cat-2): second part of the category
- - $(pkg) : name of the package
- - $(version) : version of the package
-
- @param cpv: the cpv of the current package
- @type cpv: string (cat/pkg-ver)
- @param exp: the expression to render the path from
- @type exp: string
- @returns: rendered path
- @rtype string"""
-
- if exp.find("$(") != -1:
- cat, pkg, ver, rev = system.split_cpv(cpv)
- if rev != "r0":
- ver = "%s-%s" % (ver, rev)
- exp = exp.replace("$(cat)",cat).\
- replace("$(pkg)",pkg).\
- replace("$(cat-1)",cat.split("-")[0]).\
- replace("$(cat-2)",cat.split("-")[1]).\
- replace("$(version)",ver)
- return exp
+ """Generates the correct path out of given wildcards.
+ These wildcards can be:
+ - $(cat) : category
+ - $(cat-1): first part of the category (e.g. "app")
+ - $(cat-2): second part of the category
+ - $(pkg) : name of the package
+ - $(version) : version of the package
+
+ @param cpv: the cpv of the current package
+ @type cpv: string (cat/pkg-ver)
+ @param exp: the expression to render the path from
+ @type exp: string
+ @returns: rendered path
+ @rtype string"""
+
+ if exp.find("$(") != -1:
+ cat, pkg, ver, rev = system.split_cpv(cpv)
+ if rev != "r0":
+ ver = "%s-%s" % (ver, rev)
+ exp = exp.replace("$(cat)",cat).\
+ replace("$(pkg)",pkg).\
+ replace("$(cat-1)",cat.split("-")[0]).\
+ replace("$(cat-2)",cat.split("-")[1]).\
+ replace("$(version)",ver)
+ return exp
### USE FLAG PART ###
useFlags = {} # useFlags in the file
newUseFlags = {} # useFlags as we want them to be: format: cpv -> [(file, line, useflag, (true if removed from list / false if added))]
def invert_use_flag (flag):
- """Invertes a flag.
-
- >>> invert_use_flag("foo")
- -foo
- >>> invert_use_flag("-bar")
- bar
-
- @param flag: the flag
- @type flag: string
- @returns: inverted flag
- @rtype: string
- """
-
- if flag[0] == "-":
- return flag[1:]
- else:
- return "-"+flag
+ """Invertes a flag.
+
+ >>> invert_use_flag("foo")
+ -foo
+ >>> invert_use_flag("-bar")
+ bar
+
+ @param flag: the flag
+ @type flag: string
+ @returns: inverted flag
+ @rtype: string
+ """
+
+ if flag[0] == "-":
+ return flag[1:]
+ else:
+ return "-"+flag
def sort_use_flag_list (flaglist):
- """
- Sorts a list of useflags. If a use flag starts with "+" or "-" this one is ignored for the matter of sorting.
- This functions sorts the list itself - thus does not create a new one. But for convenience it returns the list too.
-
- @param flaglist: the list of useflags
- @type flaglist: string[]
-
- @returns: the sorted list (Note: it is the same as the one passed in)
- @rtype: string[]
- """
-
- def flag_key (flag):
- if flag.startswith(("+","-")):
- return flag[1:]
- else:
- return flag
-
- flaglist.sort(key = flag_key)
- return flaglist
+ """
+ Sorts a list of useflags. If a use flag starts with "+" or "-" this one is ignored for the matter of sorting.
+ This functions sorts the list itself - thus does not create a new one. But for convenience it returns the list too.
+
+ @param flaglist: the list of useflags
+ @type flaglist: string[]
+
+ @returns: the sorted list (Note: it is the same as the one passed in)
+ @rtype: string[]
+ """
+
+ def flag_key (flag):
+ if flag.startswith(("+","-")):
+ return flag[1:]
+ else:
+ return flag
+
+ flaglist.sort(key = flag_key)
+ return flaglist
def filter_defaults (flaglist):
- """
- Removes "+" and "-" from IUSE defaults.
+ """
+ Removes "+" and "-" from IUSE defaults.
- @param flaglist: the list of useflags
- @type flaglist: string<iterator>
+ @param flaglist: the list of useflags
+ @type flaglist: string<iterator>
- @returns: the "cleaned" list
- @rtype: string<iterator>
- """
+ @returns: the "cleaned" list
+ @rtype: string<iterator>
+ """
- for flag in flaglist:
- if flag.startswith(("+","-")):
- yield flag[1:]
- else:
- yield flag
+ for flag in flaglist:
+ if flag.startswith(("+","-")):
+ yield flag[1:]
+ else:
+ yield flag
def set_use_flag (pkg, flag):
- """Sets the useflag for a given package.
-
- @param pkg: the package
- @type pkg: string (cpv) or L{backend.Package}-object
- @param flag: the flag to set
- @type flag: string"""
-
- global useFlags, newUseFlags
-
- if not is_package(pkg):
- pkg = system.new_package(pkg) # assume cpv or gentoolkit.Package
-
- cpv = pkg.get_cpv()
- invFlag = invert_use_flag(flag)
-
- # if not saved in useFlags, get it by calling get_data() which calls grep()
- data = None
- if not cpv in useFlags:
- data = get_data(pkg, CONST.use_path())
- useFlags[cpv] = data
- else:
- data = useFlags[cpv]
-
- if not cpv in newUseFlags:
- newUseFlags[cpv] = []
-
- debug("data: %s", str(data))
- # add a useflag / delete one
- added = False
- for file, line, crit, flags in data:
- if pkg.matches(crit):
- # we have the inverted flag in the uselist/newuselist --> delete it
- if invFlag in flags or (file, line, invFlag, False) in newUseFlags[cpv] or (file, line, flag, True) in newUseFlags[cpv]:
- if added: del newUseFlags[-1] # we currently added it as an extra option - delete it
- added = True
- jumpOut = False
- for t in ((file, line, invFlag, False),(file, line, flag, True)):
- if t in newUseFlags[cpv]:
- newUseFlags[cpv].remove(t)
- jumpOut = True
- # break # don't break as both cases can be valid (see below)
- if not jumpOut:
- newUseFlags[cpv].append((file, line, invFlag, True))
-
- # we removed the inverted from package.use - but it is still enabled somewhere else
- # so set it explicitly here
- if invFlag in pkg.get_actual_use_flags():
- newUseFlags[cpv].append((file, line, flag, False))
- break
-
- # we want to duplicate the flag --> ignore
- elif flag in flags:
- added = True # emulate adding
- break
-
- # add as an extra flag
- else:
- if not added: newUseFlags[cpv].append((file, line, flag, False))
- added = True
-
- # create a new line
- if not added:
- path = CONST.use_path()
- if CONST.use_path_is_dir():
- path = os.path.join(CONST.use_path(), generate_path(cpv, CONFIG["usefile"]))
- try:
- newUseFlags[cpv].remove((path, -1, invFlag, False))
- except ValueError: # not in UseFlags
- newUseFlags[cpv].append((path, -1, flag, False))
-
- newUseFlags[cpv] = unique_array(newUseFlags[cpv])
- debug("newUseFlags: %s", str(newUseFlags))
+ """Sets the useflag for a given package.
+
+ @param pkg: the package
+ @type pkg: string (cpv) or L{backend.Package}-object
+ @param flag: the flag to set
+ @type flag: string"""
+
+ global useFlags, newUseFlags
+
+ if not is_package(pkg):
+ pkg = system.new_package(pkg) # assume cpv or gentoolkit.Package
+
+ cpv = pkg.get_cpv()
+ invFlag = invert_use_flag(flag)
+
+ # if not saved in useFlags, get it by calling get_data() which calls grep()
+ data = None
+ if not cpv in useFlags:
+ data = get_data(pkg, CONST.use_path())
+ useFlags[cpv] = data
+ else:
+ data = useFlags[cpv]
+
+ if not cpv in newUseFlags:
+ newUseFlags[cpv] = []
+
+ debug("data: %s", str(data))
+ # add a useflag / delete one
+ added = False
+ for file, line, crit, flags in data:
+ if pkg.matches(crit):
+ # we have the inverted flag in the uselist/newuselist --> delete it
+ if invFlag in flags or (file, line, invFlag, False) in newUseFlags[cpv] or (file, line, flag, True) in newUseFlags[cpv]:
+ if added: del newUseFlags[-1] # we currently added it as an extra option - delete it
+ added = True
+ jumpOut = False
+ for t in ((file, line, invFlag, False),(file, line, flag, True)):
+ if t in newUseFlags[cpv]:
+ newUseFlags[cpv].remove(t)
+ jumpOut = True
+ # break # don't break as both cases can be valid (see below)
+ if not jumpOut:
+ newUseFlags[cpv].append((file, line, invFlag, True))
+
+ # we removed the inverted from package.use - but it is still enabled somewhere else
+ # so set it explicitly here
+ if invFlag in pkg.get_actual_use_flags():
+ newUseFlags[cpv].append((file, line, flag, False))
+ break
+
+ # we want to duplicate the flag --> ignore
+ elif flag in flags:
+ added = True # emulate adding
+ break
+
+ # add as an extra flag
+ else:
+ if not added: newUseFlags[cpv].append((file, line, flag, False))
+ added = True
+
+ # create a new line
+ if not added:
+ path = CONST.use_path()
+ if CONST.use_path_is_dir():
+ path = os.path.join(CONST.use_path(), generate_path(cpv, CONFIG["usefile"]))
+ try:
+ newUseFlags[cpv].remove((path, -1, invFlag, False))
+ except ValueError: # not in UseFlags
+ newUseFlags[cpv].append((path, -1, flag, False))
+
+ newUseFlags[cpv] = unique_array(newUseFlags[cpv])
+ debug("newUseFlags: %s", str(newUseFlags))
def remove_new_use_flags (cpv):
- """Removes all new use-flags for a specific package.
-
- @param cpv: the package for which to remove the flags
- @type cpv: string (cpv) or L{backend.Package}-object"""
-
- if is_package(cpv):
- cpv = cpv.get_cpv()
-
- try:
- del newUseFlags[cpv]
- except KeyError:
- pass
+ """Removes all new use-flags for a specific package.
+
+ @param cpv: the package for which to remove the flags
+ @type cpv: string (cpv) or L{backend.Package}-object"""
+
+ if is_package(cpv):
+ cpv = cpv.get_cpv()
+
+ try:
+ del newUseFlags[cpv]
+ except KeyError:
+ pass
def get_new_use_flags (cpv):
- """Gets all the new use-flags for a specific package.
-
- @param cpv: the package from which to get the flags
- @type cpv: string (cpv) or L{backend.Package}-object
- @returns: list of flags
- @rtype: string[]"""
-
- if is_package(cpv):
- cpv = cpv.get_cpv()
-
- list2return = set()
- try:
- for file, line, flag, remove in newUseFlags[cpv]:
- if remove:
- list2return.add("~"+invert_use_flag(flag))
- else:
- list2return.add(flag)
- except KeyError:
- pass
-
- return list(list2return)
+ """Gets all the new use-flags for a specific package.
+
+ @param cpv: the package from which to get the flags
+ @type cpv: string (cpv) or L{backend.Package}-object
+ @returns: list of flags
+ @rtype: string[]"""
+
+ if is_package(cpv):
+ cpv = cpv.get_cpv()
+
+ list2return = set()
+ try:
+ for file, line, flag, remove in newUseFlags[cpv]:
+ if remove:
+ list2return.add("~"+invert_use_flag(flag))
+ else:
+ list2return.add(flag)
+ except KeyError:
+ pass
+
+ return list(list2return)
def write_use_flags ():
- """This writes our changed useflags into the file."""
- global newUseFlags, useFlags
-
- def insert (flag, list):
- """Shortcut for inserting a new flag right after the package-name."""
- list.insert(1,flag)
-
- def remove (flag, list):
- """Removes a flag."""
- try:
- list.remove(flag)
- except ValueError: # flag is given as flag\n
- list.remove(flag+"\n")
- list.append("\n") #re-insert the newline
-
- # no more flags there - comment it out
- if len(list) == 1 or list[1][0] in ("#","\n"):
- list[0] = "#"+list[0]
- insert("#removed by portato#",list)
-
- file_cache = {} # cache for having to read the file only once: name->[lines]
- for cpv in newUseFlags:
- flagsToAdd = [] # this is used for collecting the flags to be inserted in a _new_ line
-
- newUseFlags[cpv].sort(key = lambda x: x[3]) # now the flags are sorted in a manner, that removal comes after appending
-
- for file, line, flag, delete in newUseFlags[cpv]:
- line = int(line) # it is saved as a string so far!
- # add new line
- if line == -1:
- flagsToAdd.append(flag)
- # change a line
- else:
- if not file in file_cache:
- # read file
- with open(file, "r") as f:
- lines = []
- i = 1
- while i < line: # stop at the given line
- lines.append(f.readline())
- i += 1
- l = f.readline().split(" ")
-
- # delete or insert
- if delete:
- remove(flag,l)
- else:
- insert(flag,l)
- lines.append(" ".join(l))
-
- # read the rest
- lines.extend(f.readlines())
-
- file_cache[file] = lines
-
- else: # in cache
- l = file_cache[file][line-1].split(" ")
- if delete:
- remove(flag, l)
- else:
- insert(flag,l)
- file_cache[file][line-1] = " ".join(l)
-
- if flagsToAdd:
- # write new lines
- msg = "\n#portato update#\n"
- if CONFIG["usePerVersion"]: # add on a per-version-base
- msg += "=%s %s\n" % (cpv, ' '.join(flagsToAdd))
- else: # add on a per-package-base
- list = system.split_cpv(cpv)
- msg += "%s/%s %s\n" % (list[0], list[1], ' '.join(flagsToAdd))
- if not file in file_cache:
- f = open(file, "a")
- f.write(msg)
- f.close()
- else:
- file_cache[file].append(msg)
-
- # write to disk
- for file in file_cache.keys():
- f = open(file, "w")
- f.writelines(file_cache[file])
- f.close()
- # reset
- useFlags = {}
- newUseFlags = {}
- system.reload_settings()
+ """This writes our changed useflags into the file."""
+ global newUseFlags, useFlags
+
+ def insert (flag, list):
+ """Shortcut for inserting a new flag right after the package-name."""
+ list.insert(1,flag)
+
+ def remove (flag, list):
+ """Removes a flag."""
+ try:
+ list.remove(flag)
+ except ValueError: # flag is given as flag\n
+ list.remove(flag+"\n")
+ list.append("\n") #re-insert the newline
+
+ # no more flags there - comment it out
+ if len(list) == 1 or list[1][0] in ("#","\n"):
+ list[0] = "#"+list[0]
+ insert("#removed by portato#",list)
+
+ file_cache = {} # cache for having to read the file only once: name->[lines]
+ for cpv in newUseFlags:
+ flagsToAdd = [] # this is used for collecting the flags to be inserted in a _new_ line
+
+ newUseFlags[cpv].sort(key = lambda x: x[3]) # now the flags are sorted in a manner, that removal comes after appending
+
+ for file, line, flag, delete in newUseFlags[cpv]:
+ line = int(line) # it is saved as a string so far!
+ # add new line
+ if line == -1:
+ flagsToAdd.append(flag)
+ # change a line
+ else:
+ if not file in file_cache:
+ # read file
+ with open(file, "r") as f:
+ lines = []
+ i = 1
+ while i < line: # stop at the given line
+ lines.append(f.readline())
+ i += 1
+ l = f.readline().split(" ")
+
+ # delete or insert
+ if delete:
+ remove(flag,l)
+ else:
+ insert(flag,l)
+ lines.append(" ".join(l))
+
+ # read the rest
+ lines.extend(f.readlines())
+
+ file_cache[file] = lines
+
+ else: # in cache
+ l = file_cache[file][line-1].split(" ")
+ if delete:
+ remove(flag, l)
+ else:
+ insert(flag,l)
+ file_cache[file][line-1] = " ".join(l)
+
+ if flagsToAdd:
+ # write new lines
+ msg = "\n#portato update#\n"
+ if CONFIG["usePerVersion"]: # add on a per-version-base
+ msg += "=%s %s\n" % (cpv, ' '.join(flagsToAdd))
+ else: # add on a per-package-base
+ list = system.split_cpv(cpv)
+ msg += "%s/%s %s\n" % (list[0], list[1], ' '.join(flagsToAdd))
+ if not file in file_cache:
+ f = open(file, "a")
+ f.write(msg)
+ f.close()
+ else:
+ file_cache[file].append(msg)
+
+ # write to disk
+ for file in file_cache.keys():
+ f = open(file, "w")
+ f.writelines(file_cache[file])
+ f.close()
+ # reset
+ useFlags = {}
+ newUseFlags = {}
+ system.reload_settings()
### MASKING PART ###
new_masked = {}
new_unmasked = {}
def set_masked (pkg, masked = True):
- """Sets the masking status of the package.
-
- @param pkg: the package from which to get the flags
- @type pkg: string (cpv) or L{backend.Package}-object
- @param masked: if True: mask it; if False: unmask it
- @type masked: boolean"""
-
- global new_masked, newunmasked
-
- if not is_package(pkg):
- pkg = system.new_package(pkg)
-
- cpv = pkg.get_cpv()
-
- if not cpv in new_unmasked:
- new_unmasked[cpv] = []
- if not cpv in new_masked:
- new_masked[cpv] = []
-
- if masked:
- link_neq = new_masked
- link_eq = new_unmasked
- path = CONST.unmask_path()
- else:
- link_neq = new_unmasked
- link_eq = new_masked
- path = CONST.mask_path()
-
- copy = link_eq[cpv][:]
- for file, line in copy:
- if line == "-1":
- link_eq[cpv].remove((file, line))
-
- copy = link_neq[cpv][:]
- for file, line in copy:
- if line != "-1":
- link_neq[cpv].remove((file, line))
-
- if masked == pkg.is_masked():
- return
-
- data = get_data(pkg, path)
- debug("data: %s", str(data))
- done = False
- for file, line, crit, flags in data:
- if pkg.matches(crit):
- link_eq[cpv].append((file, line))
- done = True
-
- if done: return
-
- if masked:
- is_dir = CONST.mask_path_is_dir()
- path = CONST.mask_path()
- else:
- is_dir = CONST.unmask_path_is_dir()
- path = CONST.unmask_path()
-
- if is_dir:
- file = os.path.join(path, generate_path(cpv, CONFIG["maskfile"]))
- else:
- file = path
-
- link_neq[cpv].append((file, "-1"))
- link_neq[cpv] = unique_array(link_neq[cpv])
- debug("new_(un)masked: %s",str(link_neq))
+ """Sets the masking status of the package.
+
+ @param pkg: the package from which to get the flags
+ @type pkg: string (cpv) or L{backend.Package}-object
+ @param masked: if True: mask it; if False: unmask it
+ @type masked: boolean"""
+
+ global new_masked, newunmasked
+
+ if not is_package(pkg):
+ pkg = system.new_package(pkg)
+
+ cpv = pkg.get_cpv()
+
+ if not cpv in new_unmasked:
+ new_unmasked[cpv] = []
+ if not cpv in new_masked:
+ new_masked[cpv] = []
+
+ if masked:
+ link_neq = new_masked
+ link_eq = new_unmasked
+ path = CONST.unmask_path()
+ else:
+ link_neq = new_unmasked
+ link_eq = new_masked
+ path = CONST.mask_path()
+
+ copy = link_eq[cpv][:]
+ for file, line in copy:
+ if line == "-1":
+ link_eq[cpv].remove((file, line))
+
+ copy = link_neq[cpv][:]
+ for file, line in copy:
+ if line != "-1":
+ link_neq[cpv].remove((file, line))
+
+ if masked == pkg.is_masked():
+ return
+
+ data = get_data(pkg, path)
+ debug("data: %s", str(data))
+ done = False
+ for file, line, crit, flags in data:
+ if pkg.matches(crit):
+ link_eq[cpv].append((file, line))
+ done = True
+
+ if done: return
+
+ if masked:
+ is_dir = CONST.mask_path_is_dir()
+ path = CONST.mask_path()
+ else:
+ is_dir = CONST.unmask_path_is_dir()
+ path = CONST.unmask_path()
+
+ if is_dir:
+ file = os.path.join(path, generate_path(cpv, CONFIG["maskfile"]))
+ else:
+ file = path
+
+ link_neq[cpv].append((file, "-1"))
+ link_neq[cpv] = unique_array(link_neq[cpv])
+ debug("new_(un)masked: %s",str(link_neq))
def remove_new_masked (cpv):
- if is_package(cpv):
- cpv = cpv.get_cpv()
-
- try:
- del new_masked[cpv]
- except KeyError:
- pass
-
- try:
- del new_unmasked[cpv]
- except KeyError:
- pass
+ if is_package(cpv):
+ cpv = cpv.get_cpv()
+
+ try:
+ del new_masked[cpv]
+ except KeyError:
+ pass
+
+ try:
+ del new_unmasked[cpv]
+ except KeyError:
+ pass
def new_masking_status (cpv):
- if is_package(cpv):
- cpv = cpv.get_cpv()
-
- def get(list):
- ret = None
- if cpv in list and list[cpv] != []:
- for file, line in list[cpv]:
- _ret = (int(line) == -1)
- if ret is not None and _ret != ret:
- error(_("Conflicting values for masking status: %s"), list)
- else:
- ret = _ret
- return ret
-
- masked = get(new_masked)
- if masked is None:
- masked = get(new_unmasked)
- if masked is not None:
- masked = not masked # revert for new_unmasked
-
- if masked is not None:
- if masked: return "masked"
- else: return "unmasked"
- else:
- return None
+ if is_package(cpv):
+ cpv = cpv.get_cpv()
+
+ def get(list):
+ ret = None
+ if cpv in list and list[cpv] != []:
+ for file, line in list[cpv]:
+ _ret = (int(line) == -1)
+ if ret is not None and _ret != ret:
+ error(_("Conflicting values for masking status: %s"), list)
+ else:
+ ret = _ret
+ return ret
+
+ masked = get(new_masked)
+ if masked is None:
+ masked = get(new_unmasked)
+ if masked is not None:
+ masked = not masked # revert for new_unmasked
+
+ if masked is not None:
+ if masked: return "masked"
+ else: return "unmasked"
+ else:
+ return None
def is_locally_masked (pkg, changes = True):
- if not is_package(pkg):
- pkg = system.new_package(pkg) # assume it is a cpv or a gentoolkit.Package
+ if not is_package(pkg):
+ pkg = system.new_package(pkg) # assume it is a cpv or a gentoolkit.Package
- if changes:
- if new_masking_status(pkg) == "masked": # we masked it ourselves, but did not save it yet
- # but sometimes, new_masking_status() returns "masked" if a package's unmask is removed
- # then it is masked by the system but not locally (except rarely exotic cases)
- if pkg.get_cpv() in new_unmasked:
- if new_unmasked[pkg.get_cpv()]: return False # assume that there only exists one entry for this package
- # else new_masking_status should have printed an error
- return True
+ if changes:
+ if new_masking_status(pkg) == "masked": # we masked it ourselves, but did not save it yet
+ # but sometimes, new_masking_status() returns "masked" if a package's unmask is removed
+ # then it is masked by the system but not locally (except rarely exotic cases)
+ if pkg.get_cpv() in new_unmasked:
+ if new_unmasked[pkg.get_cpv()]: return False # assume that there only exists one entry for this package
+ # else new_masking_status should have printed an error
+ return True
- if new_masking_status(pkg) == "unmasked": # we unmasked it
- return False
-
- list = get_data(pkg, CONST.mask_path())
+ if new_masking_status(pkg) == "unmasked": # we unmasked it
+ return False
+
+ list = get_data(pkg, CONST.mask_path())
- if not list: return False
+ if not list: return False
- for file, line, crit, fl in list:
- if pkg.matches(crit):
- return True
+ for file, line, crit, fl in list:
+ if pkg.matches(crit):
+ return True
- return False
-
+ return False
+
def write_masked ():
- global new_unmasked, new_masked
- file_cache = {}
-
- def write(cpv, file, line):
- line = int(line)
- # add new line
- if line == -1:
- msg = "\n#portato update#\n"
- if CONFIG["maskPerVersion"]:
- msg += "=%s\n" % cpv
- else:
- list = system.split_cpv(cpv)
- msg += "%s/%s\n" % (list[0],list[1])
- if not file in file_cache:
- f = open(file, "a")
- f.write(msg)
- f.close()
- else:
- file_cache[file].append(msg)
- # change a line
- else:
- if not file in file_cache:
- # read file
- f = open(file, "r")
- lines = []
- i = 1
- while i < line: # stop at the given line
- lines.append(f.readline())
- i = i+1
- # delete
- l = f.readline()
- l = "#"+l[:-1]+" # removed by portato\n"
- lines.append(l)
-
- # read the rest
- lines.extend(f.readlines())
-
- file_cache[file] = lines
- f.close()
- else: # in cache
- l = file_cache[file][line-1]
- # delete:
- l = "#"+l[:-1]+" # removed by portato\n"
- file_cache[file][line-1] = l
-
-
- for cpv in new_masked:
- for file, line in new_masked[cpv]:
- write(cpv, file, line)
-
- for cpv in new_unmasked:
- for file, line in new_unmasked[cpv]:
- write(cpv, file, line)
-
- # write to disk
- for file in file_cache.keys():
- f = open(file, "w")
- f.writelines(file_cache[file])
- f.close()
- # reset
- new_masked = {}
- new_unmasked = {}
- system.reload_settings()
+ global new_unmasked, new_masked
+ file_cache = {}
+
+ def write(cpv, file, line):
+ line = int(line)
+ # add new line
+ if line == -1:
+ msg = "\n#portato update#\n"
+ if CONFIG["maskPerVersion"]:
+ msg += "=%s\n" % cpv
+ else:
+ list = system.split_cpv(cpv)
+ msg += "%s/%s\n" % (list[0],list[1])
+ if not file in file_cache:
+ f = open(file, "a")
+ f.write(msg)
+ f.close()
+ else:
+ file_cache[file].append(msg)
+ # change a line
+ else:
+ if not file in file_cache:
+ # read file
+ f = open(file, "r")
+ lines = []
+ i = 1
+ while i < line: # stop at the given line
+ lines.append(f.readline())
+ i = i+1
+ # delete
+ l = f.readline()
+ l = "#"+l[:-1]+" # removed by portato\n"
+ lines.append(l)
+
+ # read the rest
+ lines.extend(f.readlines())
+
+ file_cache[file] = lines
+ f.close()
+ else: # in cache
+ l = file_cache[file][line-1]
+ # delete:
+ l = "#"+l[:-1]+" # removed by portato\n"
+ file_cache[file][line-1] = l
+
+
+ for cpv in new_masked:
+ for file, line in new_masked[cpv]:
+ write(cpv, file, line)
+
+ for cpv in new_unmasked:
+ for file, line in new_unmasked[cpv]:
+ write(cpv, file, line)
+
+ # write to disk
+ for file in file_cache.keys():
+ f = open(file, "w")
+ f.writelines(file_cache[file])
+ f.close()
+ # reset
+ new_masked = {}
+ new_unmasked = {}
+ system.reload_settings()
### TESTING PART ###
newTesting = {}
arch = ""
def remove_new_testing (cpv):
- if is_package(cpv):
- cpv = cpv.get_cpv()
-
- try:
- del newTesting[cpv]
- except KeyError:
- pass
+ if is_package(cpv):
+ cpv = cpv.get_cpv()
+
+ try:
+ del newTesting[cpv]
+ except KeyError:
+ pass
def new_testing_status (cpv):
- if is_package(cpv):
- cpv = cpv.get_cpv()
+ if is_package(cpv):
+ cpv = cpv.get_cpv()
- if cpv in newTesting:
- for file, line in newTesting[cpv]:
- if line == "-1": return False
- else: return True
+ if cpv in newTesting:
+ for file, line in newTesting[cpv]:
+ if line == "-1": return False
+ else: return True
- return None
+ return None
def set_testing (pkg, enable):
- """Enables the package for installing when it is marked as testing (~ARCH).
- @param pkg: the package
- @type pkg: string (cpv) or L{backend.Package}-object
- @param enable: controls whether to enable (True) or disable (False) for test-installing
- @type enable: boolean"""
-
- global arch, newTesting
- if not is_package(pkg):
- pkg = system.new_package(pkg)
-
- arch = pkg.get_global_settings("ARCH")
- cpv = pkg.get_cpv()
- if not cpv in newTesting:
- newTesting[cpv] = []
-
- for file, line in newTesting[cpv]:
- if (enable and line != "-1") or (not enable and line == "-1"):
- newTesting[cpv].remove((file, line))
-
- if (enable and not pkg.is_testing()) or (not enable and pkg.is_testing()):
- return
-
- if not enable:
- test = get_data(pkg, CONST.testing_path())
- debug("data (test): %s", str(test))
- for file, line, crit, flags in test:
- if pkg.matches(crit) and flags[0] == "~"+arch:
- newTesting[cpv].append((file, line))
- else:
- if CONST.testing_path_is_dir():
- file = os.path.join(CONST.testing_path(), generate_path(cpv, CONFIG["testingfile"]))
- else:
- file = CONST.testing_path()
- newTesting[cpv].append((file, "-1"))
-
- newTesting[cpv] = unique_array(newTesting[cpv])
- debug("newTesting: %s",str(newTesting))
+ """Enables the package for installing when it is marked as testing (~ARCH).
+ @param pkg: the package
+ @type pkg: string (cpv) or L{backend.Package}-object
+ @param enable: controls whether to enable (True) or disable (False) for test-installing
+ @type enable: boolean"""
+
+ global arch, newTesting
+ if not is_package(pkg):
+ pkg = system.new_package(pkg)
+
+ arch = pkg.get_global_settings("ARCH")
+ cpv = pkg.get_cpv()
+ if not cpv in newTesting:
+ newTesting[cpv] = []
+
+ for file, line in newTesting[cpv]:
+ if (enable and line != "-1") or (not enable and line == "-1"):
+ newTesting[cpv].remove((file, line))
+
+ if (enable and not pkg.is_testing()) or (not enable and pkg.is_testing()):
+ return
+
+ if not enable:
+ test = get_data(pkg, CONST.testing_path())
+ debug("data (test): %s", str(test))
+ for file, line, crit, flags in test:
+ if pkg.matches(crit) and flags[0] == "~"+arch:
+ newTesting[cpv].append((file, line))
+ else:
+ if CONST.testing_path_is_dir():
+ file = os.path.join(CONST.testing_path(), generate_path(cpv, CONFIG["testingfile"]))
+ else:
+ file = CONST.testing_path()
+ newTesting[cpv].append((file, "-1"))
+
+ newTesting[cpv] = unique_array(newTesting[cpv])
+ debug("newTesting: %s",str(newTesting))
def write_testing ():
- global arch, newTesting
- file_cache = {}
-
- for cpv in newTesting:
- for file, line in newTesting[cpv]:
- line = int(line)
- # add new line
- if line == -1:
- msg = "\n#portato update#\n"
- if CONFIG["testingPerVersion"]:
- msg += "=%s ~%s\n" % (cpv, arch)
- else:
- list = system.split_cpv(cpv)
- msg += "%s/%s ~%s\n" % (list[0],list[1],arch)
- if not file in file_cache:
- f = open(file, "a")
- f.write(msg)
- f.close()
- else:
- file_cache[file].append(msg)
- # change a line
- else:
- if not file in file_cache:
- # read file
- f = open(file, "r")
- lines = []
- i = 1
- while i < line: # stop at the given line
- lines.append(f.readline())
- i = i+1
- # delete
- l = f.readline()
- l = "#"+l[:-1]+" # removed by portato\n"
- lines.append(l)
-
- # read the rest
- lines.extend(f.readlines())
-
- file_cache[file] = lines
- f.close()
- else: # in cache
- l = file_cache[file][line-1]
- # delete:
- l = "#"+l[:-1]+" # removed by portato\n"
- file_cache[file][line-1] = l
-
- # write to disk
- for file in file_cache.keys():
- f = open(file, "w")
- f.writelines(file_cache[file])
- f.close()
- # reset
- newTesting = {}
- system.reload_settings()
+ global arch, newTesting
+ file_cache = {}
+
+ for cpv in newTesting:
+ for file, line in newTesting[cpv]:
+ line = int(line)
+ # add new line
+ if line == -1:
+ msg = "\n#portato update#\n"
+ if CONFIG["testingPerVersion"]:
+ msg += "=%s ~%s\n" % (cpv, arch)
+ else:
+ list = system.split_cpv(cpv)
+ msg += "%s/%s ~%s\n" % (list[0],list[1],arch)
+ if not file in file_cache:
+ f = open(file, "a")
+ f.write(msg)
+ f.close()
+ else:
+ file_cache[file].append(msg)
+ # change a line
+ else:
+ if not file in file_cache:
+ # read file
+ f = open(file, "r")
+ lines = []
+ i = 1
+ while i < line: # stop at the given line
+ lines.append(f.readline())
+ i = i+1
+ # delete
+ l = f.readline()
+ l = "#"+l[:-1]+" # removed by portato\n"
+ lines.append(l)
+
+ # read the rest
+ lines.extend(f.readlines())
+
+ file_cache[file] = lines
+ f.close()
+ else: # in cache
+ l = file_cache[file][line-1]
+ # delete:
+ l = "#"+l[:-1]+" # removed by portato\n"
+ file_cache[file][line-1] = l
+
+ # write to disk
+ for file in file_cache.keys():
+ f = open(file, "w")
+ f.writelines(file_cache[file])
+ f.close()
+ # reset
+ newTesting = {}
+ system.reload_settings()
diff --git a/portato/backend/package.py b/portato/backend/package.py
index 6d73a42..e4b2082 100644
--- a/portato/backend/package.py
+++ b/portato/backend/package.py
@@ -18,396 +18,396 @@ from ..dependency import DependencyTree
from . import _Package, system, flags
class Package (_Package):
- """This is a class abstracting a normal package which can be installed."""
-
- def __init__ (self, cpv):
- """Constructor.
-
- @param cpv: The cpv which describes the package to create.
- @type cpv: string (cat/pkg-ver)"""
-
- self._cpv = cpv
-
- #
- # implemented
- #
-
- def set_testing(self, enable = True):
- """Sets the actual testing status of the package.
-
- @param enable: if True it is masked as stable; if False it is marked as testing
- @type enable: boolean"""
-
- flags.set_testing(self, enable)
-
- def remove_new_testing(self):
- """Removes possible changed testing status."""
-
- flags.remove_new_testing(self.get_cpv())
-
- def set_masked (self, masking = False):
- """Sets the masking status of the package.
-
- @param masking: if True: mask it; if False: unmask it
- @type masking: boolean"""
-
- flags.set_masked(self, masked = masking)
-
- def remove_new_masked (self):
- """Removes possible changed masking status."""
-
- flags.remove_new_masked(self.get_cpv())
-
- def is_locally_masked (self):
- """Checks whether the package is masked by the user.
-
- @returns: True if masked by the user; False if not
- @rtype: bool"""
-
- return flags.is_locally_masked(self)
-
- def get_new_use_flags (self):
- """Returns a list of the new useflags, i.e. these flags which are not written to the portage-system yet.
-
- @returns: list of flags or []
- @rtype: string[]"""
-
- return flags.get_new_use_flags(self)
-
- def get_actual_use_flags (self):
- """This returns all currently set use-flags including the new ones.
-
- @return: list of flags
- @rtype: string[]"""
-
- i_flags = self.get_global_settings("USE", installed = False).split()
- m_flags = system.get_global_settings("USE").split()
- for f in self.get_new_use_flags():
- removed = False
-
- if f[0] == "~":
- f = f[1:]
- removed = True
-
- invf = flags.invert_use_flag(f)
-
- if f[0] == '-':
- if invf in i_flags and not (removed and invf in m_flags):
- i_flags.remove(invf)
-
- elif f not in i_flags:
- if not (removed and invf in m_flags):
- i_flags.append(f)
-
- return i_flags
-
- def set_use_flag (self, flag):
- """Set a use-flag.
-
- @param flag: the flag to set
- @type flag: string"""
-
- flags.set_use_flag(self, flag)
-
- def remove_new_use_flags (self):
- """Remove all the new use-flags."""
-
- flags.remove_new_use_flags(self)
-
- def use_expanded (self, flag, suggest = None):
- """Tests whether a useflag is an expanded one. If it is, this method returns the USE_EXPAND-value.
-
- @param flag: the flag to check
- @type flag: string
- @param suggest: try this suggestion first
- @type suggest: string
- @returns: USE_EXPAND-value on success
- @rtype: string or None"""
-
- if suggest is not None:
- if flag.startswith(suggest.lower()):
- return suggest
-
- for exp in self.get_global_settings("USE_EXPAND").split():
- lexp = exp.lower()
- if flag.startswith(lexp):
- return exp
-
- return None
-
- def get_cpv(self):
- """Returns full Category/Package-Version string.
-
- @returns: the cpv
- @rtype: string"""
-
- return self._cpv
-
- def get_cp (self):
- """Returns the cp-string.
-
- @returns: category/package.
- @rtype: string"""
-
- return self.get_category()+"/"+self.get_name()
-
- def get_slot_cp (self):
- """Returns the current cp followed by a colon and the slot-number.
-
- @returns: cp:slot
- @rtype: string"""
-
- return ("%s:%s" % (self.get_cp(), self.get_package_settings("SLOT")))
-
- def get_package_path(self):
- """Returns the path to where the ChangeLog, Manifest, .ebuild files reside.
-
- @returns: path to the package files
- @rtype: string"""
-
- p = self.get_ebuild_path()
- sp = p.split("/")
- if sp:
- return "/".join(sp[:-1])
-
- def get_dependencies (self):
- """
- Returns the tree of dependencies that this package needs.
-
- @rtype: L{DependencyTree}
- """
- deps = " ".join(map(self.get_package_settings, ("RDEPEND", "PDEPEND", "DEPEND")))
- deps = paren_reduce(deps)
-
- tree = DependencyTree()
-
- def add (tree, deps):
- it = iter(deps)
- for dep in it:
- if hasattr(dep, "__iter__"):
- debug("Following dep is an unsupposed list: %s", dep)
- assert(len(dep) == 1)
- dep = dep[0]
- if dep.endswith("?"):
- ntree = tree.add_flag(dep[:-1])
- n = it.next()
- if not hasattr(n, "__iter__"):
- n = (n,)
- add(ntree, n)
-
- elif dep == "||":
- n = it.next() # skip
- if not hasattr(n, "__iter__"):
- n = [n]
- else:
- n = list(n)
-
- tree.add_or(n)
-
- else:
- tree.add(dep)
-
- add(tree, deps)
- return tree
-
- #
- # Not implemented
- #
-
- def get_name(self):
- """Returns base name of package, no category nor version.
-
- @returns: base-name
- @rtype: string"""
-
- raise NotImplementedError
-
- def get_version(self):
- """Returns version of package, with (optional) revision number.
-
- @returns: version-rev
- @rtype: string"""
-
- raise NotImplementedError
-
- def get_category(self):
- """Returns category of package.
-
- @returns: category
- @rtype: string"""
-
- raise NotImplementedError
-
- def is_installed(self):
- """Returns true if this package is installed (merged).
- @rtype: boolean"""
-
- raise NotImplementedError
-
- def is_in_overlay(self):
- """Returns true if the package is in an overlay.
- @rtype: boolean"""
-
- raise NotImplementedError
-
- def get_overlay_path(self):
- """Returns the path to the current overlay.
- @rtype: string"""
-
- raise NotImplementedError
-
- def is_in_system (self):
- """Returns False if the package could not be found in the portage system.
-
- @return: True if in portage system; else False
- @rtype: boolean"""
-
- raise NotImplementedError
-
- def is_missing_keyword(self):
- """Returns True if the package is missing the needed keyword.
-
- @return: True if keyword is missing; else False
- @rtype: boolean"""
-
- raise NotImplementedError
-
- def is_testing(self, use_keywords = True):
- """Checks whether a package is marked as testing.
-
- @param use_keywords: Controls whether possible keywords are taken into account or not.
- @type use_keywords: boolean
- @returns: True if the package is marked as testing; else False.
- @rtype: boolean"""
-
- raise NotImplementedError
-
- def is_masked (self, use_changed = True):
- """Returns True if either masked by package.mask or by profile.
-
- @param use_changed: Controls, whether changes applied to masking keywords are taken into account.
- @type use_changed: boolean
- @returns: True if masked / False otherwise
- @rtype: boolean"""
-
- raise NotImplementedError
-
- def get_masking_reason (self):
- """Returns the reason for masking the package. If this is not possible for the system, return None.
-
- @returns: the reason for masking the package
- @rtype: string"""
-
- def get_iuse_flags (self, installed = False, removeForced = True):
- """Returns a list of _all_ useflags for this package, i.e. all useflags you can set for this package.
-
- @param installed: do not take the ones stated in the ebuild, but the ones it has been installed with
- @type installed: boolean
- @param removeForced: remove forced flags (i.e. usemask / useforce) from the iuse flags as they cannot be set from the user
- @type removeForced: boolean
-
- @returns: list of use-flags
- @rtype: string[]"""
-
- raise NotImplementedError
-
- def get_matched_dep_packages (self, depvar):
- """This function looks for all dependencies which are resolved. In normal case it makes only sense for installed packages, but should work for uninstalled ones too.
-
- @param depvar: the dependency variables (RDEPEND, PDEPEND, DEPEND) to use
- @type depvar: string[]
-
- @returns: unique list of dependencies resolved (with elements like "<=net-im/foobar-1.2.3")
- @rtype: string[]
-
- @raises portato.DependencyCalcError: when an error occured during executing portage.dep_check()"""
-
- raise NotImplementedError
-
- def get_dep_packages (self, depvar = ["RDEPEND", "PDEPEND", "DEPEND"], with_criterions = False):
- """Returns a cpv-list of packages on which this package depends and which have not been installed yet. This does not check the dependencies in a recursive manner.
-
- @param depvar: the dependency variables (RDEPEND, PDEPEND, DEPEND) to use
- @type depvar: string[]
- @param with_criterions: return also the criterions
- @type with_criterions: boolean
-
- @returns: list of cpvs on which the package depend (and if wanted also the criterions)
- @rtype: string[] or (string, string)[]
-
- @raises portato.BlockedException: when a package in the dependency-list is blocked by an installed one
- @raises portato.PackageNotFoundException: when a package in the dependency list could not be found in the system
- @raises portato.DependencyCalcError: when an error occured during executing portage.dep_check()"""
-
- raise NotImplementedError
-
- def get_global_settings(self, key, installed = True):
- """Returns the value of a global setting, i.e. ARCH, USE, ROOT, DISTDIR etc.
-
- @param key: the setting to return
- @type key: string
- @param installed: get the installed settings or the ebuild settings
- @type installed: boolean
- @returns: the value of this setting
- @rtype: string"""
-
- raise NotImplementedError
-
- def get_ebuild_path(self):
- """Returns the complete path to the .ebuild file.
-
- @rtype: string"""
-
- raise NotImplementedError
-
- def get_files (self):
- """
- Returns an iterator over the installed files of a package.
- If the package is not installed, the iterator should be "empty".
-
- @returns: the installed files
- @rtype: string<iterator>
- """
-
- raise NotImplementedError
-
- def get_package_settings(self, var, installed = True):
- """Returns a package specific setting, such as DESCRIPTION, SRC_URI, IUSE ...
-
- @param var: the setting to get
- @type var: string
- @param installed: take the vartree or the porttree
- @type installed: boolean
-
- @returns: the value of the setting
- @rtype: string"""
-
- raise NotImplementedError
-
- def get_installed_use_flags(self):
- """Returns _all_ (not only the package-specific) useflags which were set at the installation time of the package.
-
- @returns: list of use flags
- @rtype: string[]"""
-
- raise NotImplementedError
-
- def compare_version(self, other):
- """Compares this package's version to another's CPV; returns -1, 0, 1.
-
- @param other: the other package
- @type other: Package
- @returns: -1, 0 or 1
- @rtype: int"""
-
- raise NotImplementedError
-
- def matches (self, criterion):
- """This checks, whether this package matches a specific versioning criterion - e.g.: "<=net-im/foobar-1.2".
-
- @param criterion: the criterion to match against
- @type criterion: string
- @returns: True if matches; False if not
- @rtype: boolean"""
-
- raise NotImplementedError
+ """This is a class abstracting a normal package which can be installed."""
+
+ def __init__ (self, cpv):
+ """Constructor.
+
+ @param cpv: The cpv which describes the package to create.
+ @type cpv: string (cat/pkg-ver)"""
+
+ self._cpv = cpv
+
+ #
+ # implemented
+ #
+
+ def set_testing(self, enable = True):
+ """Sets the actual testing status of the package.
+
+ @param enable: if True it is masked as stable; if False it is marked as testing
+ @type enable: boolean"""
+
+ flags.set_testing(self, enable)
+
+ def remove_new_testing(self):
+ """Removes possible changed testing status."""
+
+ flags.remove_new_testing(self.get_cpv())
+
+ def set_masked (self, masking = False):
+ """Sets the masking status of the package.
+
+ @param masking: if True: mask it; if False: unmask it
+ @type masking: boolean"""
+
+ flags.set_masked(self, masked = masking)
+
+ def remove_new_masked (self):
+ """Removes possible changed masking status."""
+
+ flags.remove_new_masked(self.get_cpv())
+
+ def is_locally_masked (self):
+ """Checks whether the package is masked by the user.
+
+ @returns: True if masked by the user; False if not
+ @rtype: bool"""
+
+ return flags.is_locally_masked(self)
+
+ def get_new_use_flags (self):
+ """Returns a list of the new useflags, i.e. these flags which are not written to the portage-system yet.
+
+ @returns: list of flags or []
+ @rtype: string[]"""
+
+ return flags.get_new_use_flags(self)
+
+ def get_actual_use_flags (self):
+ """This returns all currently set use-flags including the new ones.
+
+ @return: list of flags
+ @rtype: string[]"""
+
+ i_flags = self.get_global_settings("USE", installed = False).split()
+ m_flags = system.get_global_settings("USE").split()
+ for f in self.get_new_use_flags():
+ removed = False
+
+ if f[0] == "~":
+ f = f[1:]
+ removed = True
+
+ invf = flags.invert_use_flag(f)
+
+ if f[0] == '-':
+ if invf in i_flags and not (removed and invf in m_flags):
+ i_flags.remove(invf)
+
+ elif f not in i_flags:
+ if not (removed and invf in m_flags):
+ i_flags.append(f)
+
+ return i_flags
+
+ def set_use_flag (self, flag):
+ """Set a use-flag.
+
+ @param flag: the flag to set
+ @type flag: string"""
+
+ flags.set_use_flag(self, flag)
+
+ def remove_new_use_flags (self):
+ """Remove all the new use-flags."""
+
+ flags.remove_new_use_flags(self)
+
+ def use_expanded (self, flag, suggest = None):
+ """Tests whether a useflag is an expanded one. If it is, this method returns the USE_EXPAND-value.
+
+ @param flag: the flag to check
+ @type flag: string
+ @param suggest: try this suggestion first
+ @type suggest: string
+ @returns: USE_EXPAND-value on success
+ @rtype: string or None"""
+
+ if suggest is not None:
+ if flag.startswith(suggest.lower()):
+ return suggest
+
+ for exp in self.get_global_settings("USE_EXPAND").split():
+ lexp = exp.lower()
+ if flag.startswith(lexp):
+ return exp
+
+ return None
+
+ def get_cpv(self):
+ """Returns full Category/Package-Version string.
+
+ @returns: the cpv
+ @rtype: string"""
+
+ return self._cpv
+
+ def get_cp (self):
+ """Returns the cp-string.
+
+ @returns: category/package.
+ @rtype: string"""
+
+ return self.get_category()+"/"+self.get_name()
+
+ def get_slot_cp (self):
+ """Returns the current cp followed by a colon and the slot-number.
+
+ @returns: cp:slot
+ @rtype: string"""
+
+ return ("%s:%s" % (self.get_cp(), self.get_package_settings("SLOT")))
+
+ def get_package_path(self):
+ """Returns the path to where the ChangeLog, Manifest, .ebuild files reside.
+
+ @returns: path to the package files
+ @rtype: string"""
+
+ p = self.get_ebuild_path()
+ sp = p.split("/")
+ if sp:
+ return "/".join(sp[:-1])
+
+ def get_dependencies (self):
+ """
+ Returns the tree of dependencies that this package needs.
+
+ @rtype: L{DependencyTree}
+ """
+ deps = " ".join(map(self.get_package_settings, ("RDEPEND", "PDEPEND", "DEPEND")))
+ deps = paren_reduce(deps)
+
+ tree = DependencyTree()
+
+ def add (tree, deps):
+ it = iter(deps)
+ for dep in it:
+ if hasattr(dep, "__iter__"):
+ debug("Following dep is an unsupposed list: %s", dep)
+ assert(len(dep) == 1)
+ dep = dep[0]
+ if dep.endswith("?"):
+ ntree = tree.add_flag(dep[:-1])
+ n = it.next()
+ if not hasattr(n, "__iter__"):
+ n = (n,)
+ add(ntree, n)
+
+ elif dep == "||":
+ n = it.next() # skip
+ if not hasattr(n, "__iter__"):
+ n = [n]
+ else:
+ n = list(n)
+
+ tree.add_or(n)
+
+ else:
+ tree.add(dep)
+
+ add(tree, deps)
+ return tree
+
+ #
+ # Not implemented
+ #
+
+ def get_name(self):
+ """Returns base name of package, no category nor version.
+
+ @returns: base-name
+ @rtype: string"""
+
+ raise NotImplementedError
+
+ def get_version(self):
+ """Returns version of package, with (optional) revision number.
+
+ @returns: version-rev
+ @rtype: string"""
+
+ raise NotImplementedError
+
+ def get_category(self):
+ """Returns category of package.
+
+ @returns: category
+ @rtype: string"""
+
+ raise NotImplementedError
+
+ def is_installed(self):
+ """Returns true if this package is installed (merged).
+ @rtype: boolean"""
+
+ raise NotImplementedError
+
+ def is_in_overlay(self):
+ """Returns true if the package is in an overlay.
+ @rtype: boolean"""
+
+ raise NotImplementedError
+
+ def get_overlay_path(self):
+ """Returns the path to the current overlay.
+ @rtype: string"""
+
+ raise NotImplementedError
+
+ def is_in_system (self):
+ """Returns False if the package could not be found in the portage system.
+
+ @return: True if in portage system; else False
+ @rtype: boolean"""
+
+ raise NotImplementedError
+
+ def is_missing_keyword(self):
+ """Returns True if the package is missing the needed keyword.
+
+ @return: True if keyword is missing; else False
+ @rtype: boolean"""
+
+ raise NotImplementedError
+
+ def is_testing(self, use_keywords = True):
+ """Checks whether a package is marked as testing.
+
+ @param use_keywords: Controls whether possible keywords are taken into account or not.
+ @type use_keywords: boolean
+ @returns: True if the package is marked as testing; else False.
+ @rtype: boolean"""
+
+ raise NotImplementedError
+
+ def is_masked (self, use_changed = True):
+ """Returns True if either masked by package.mask or by profile.
+
+ @param use_changed: Controls, whether changes applied to masking keywords are taken into account.
+ @type use_changed: boolean
+ @returns: True if masked / False otherwise
+ @rtype: boolean"""
+
+ raise NotImplementedError
+
+ def get_masking_reason (self):
+ """Returns the reason for masking the package. If this is not possible for the system, return None.
+
+ @returns: the reason for masking the package
+ @rtype: string"""
+
+ def get_iuse_flags (self, installed = False, removeForced = True):
+ """Returns a list of _all_ useflags for this package, i.e. all useflags you can set for this package.
+
+ @param installed: do not take the ones stated in the ebuild, but the ones it has been installed with
+ @type installed: boolean
+ @param removeForced: remove forced flags (i.e. usemask / useforce) from the iuse flags as they cannot be set from the user
+ @type removeForced: boolean
+
+ @returns: list of use-flags
+ @rtype: string[]"""
+
+ raise NotImplementedError
+
+ def get_matched_dep_packages (self, depvar):
+ """This function looks for all dependencies which are resolved. In normal case it makes only sense for installed packages, but should work for uninstalled ones too.
+
+ @param depvar: the dependency variables (RDEPEND, PDEPEND, DEPEND) to use
+ @type depvar: string[]
+
+ @returns: unique list of dependencies resolved (with elements like "<=net-im/foobar-1.2.3")
+ @rtype: string[]
+
+ @raises portato.DependencyCalcError: when an error occured during executing portage.dep_check()"""
+
+ raise NotImplementedError
+
+ def get_dep_packages (self, depvar = ["RDEPEND", "PDEPEND", "DEPEND"], with_criterions = False):
+ """Returns a cpv-list of packages on which this package depends and which have not been installed yet. This does not check the dependencies in a recursive manner.
+
+ @param depvar: the dependency variables (RDEPEND, PDEPEND, DEPEND) to use
+ @type depvar: string[]
+ @param with_criterions: return also the criterions
+ @type with_criterions: boolean
+
+ @returns: list of cpvs on which the package depend (and if wanted also the criterions)
+ @rtype: string[] or (string, string)[]
+
+ @raises portato.BlockedException: when a package in the dependency-list is blocked by an installed one
+ @raises portato.PackageNotFoundException: when a package in the dependency list could not be found in the system
+ @raises portato.DependencyCalcError: when an error occured during executing portage.dep_check()"""
+
+ raise NotImplementedError
+
+ def get_global_settings(self, key, installed = True):
+ """Returns the value of a global setting, i.e. ARCH, USE, ROOT, DISTDIR etc.
+
+ @param key: the setting to return
+ @type key: string
+ @param installed: get the installed settings or the ebuild settings
+ @type installed: boolean
+ @returns: the value of this setting
+ @rtype: string"""
+
+ raise NotImplementedError
+
+ def get_ebuild_path(self):
+ """Returns the complete path to the .ebuild file.
+
+ @rtype: string"""
+
+ raise NotImplementedError
+
+ def get_files (self):
+ """
+ Returns an iterator over the installed files of a package.
+ If the package is not installed, the iterator should be "empty".
+
+ @returns: the installed files
+ @rtype: string<iterator>
+ """
+
+ raise NotImplementedError
+
+ def get_package_settings(self, var, installed = True):
+ """Returns a package specific setting, such as DESCRIPTION, SRC_URI, IUSE ...
+
+ @param var: the setting to get
+ @type var: string
+ @param installed: take the vartree or the porttree
+ @type installed: boolean
+
+ @returns: the value of the setting
+ @rtype: string"""
+
+ raise NotImplementedError
+
+ def get_installed_use_flags(self):
+ """Returns _all_ (not only the package-specific) useflags which were set at the installation time of the package.
+
+ @returns: list of use flags
+ @rtype: string[]"""
+
+ raise NotImplementedError
+
+ def compare_version(self, other):
+ """Compares this package's version to another's CPV; returns -1, 0, 1.
+
+ @param other: the other package
+ @type other: Package
+ @returns: -1, 0 or 1
+ @rtype: int"""
+
+ raise NotImplementedError
+
+ def matches (self, criterion):
+ """This checks, whether this package matches a specific versioning criterion - e.g.: "<=net-im/foobar-1.2".
+
+ @param criterion: the criterion to match against
+ @type criterion: string
+ @returns: True if matches; False if not
+ @rtype: boolean"""
+
+ raise NotImplementedError
diff --git a/portato/backend/portage/__init__.py b/portato/backend/portage/__init__.py
index be6cce6..02a4a82 100644
--- a/portato/backend/portage/__init__.py
+++ b/portato/backend/portage/__init__.py
@@ -17,8 +17,8 @@ from portage import VERSION as PV
VERSION = tuple(map(int, (x.split("_")[0] for x in PV.split("."))))
if VERSION >= (2, 2):
- from .system_22 import PortageSystem_22 as PortageSystem
- from .package_22 import PortagePackage_22 as PortagePackage
+ from .system_22 import PortageSystem_22 as PortageSystem
+ from .package_22 import PortagePackage_22 as PortagePackage
else:
- from .system import PortageSystem
- from .package import PortagePackage
+ from .system import PortageSystem
+ from .package import PortagePackage
diff --git a/portato/backend/portage/package.py b/portato/backend/portage/package.py
index 351b7e0..0270029 100644
--- a/portato/backend/portage/package.py
+++ b/portato/backend/portage/package.py
@@ -21,294 +21,294 @@ from ...helper import debug, error, unique_array
import portage
try:
- import portage.dep as portage_dep
+ import portage.dep as portage_dep
except ImportError:
- import portage_dep
+ import portage_dep
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._scpv = system.split_cpv(self._cpv)
-
- if not self._scpv:
- raise ValueError("invalid cpv: %s" % cpv)
-
- self._settings = system.settings
- self._settingslock = system.settings.settingslock
- self._settings_installed = None
-
- self._trees = system.settings.trees
-
- self.forced_flags = set()
-
- with self._settingslock:
- self._init_settings(True)
- 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
-
- if self._status and len(self._status) == 1 and self._status[0] == "corrupted":
- self._status = None
-
- def _init_settings (self, installed):
- inst = (installed and self.is_installed()) or (self.is_installed() and not self.is_in_system())
-
- if self._settings_installed is not None and self._settings_installed != inst:
- self._settings.settings.reset()
-
- self._settings_installed = inst
-
- if inst:
- dbapi = self._settings.vartree.dbapi
- else:
- dbapi = self._settings.porttree.dbapi
-
- self._settings.settings.setcpv(self.get_cpv(), mydb = dbapi)
-
- def get_name(self):
- return self._scpv[1]
-
- def get_version(self):
- v = self._scpv[2]
- if self._scpv[3] != "r0":
- v += "-" + self._scpv[3]
- return v
-
- def get_category(self):
- return self._scpv[0]
-
- def is_installed(self):
- return self._settings.vartree.dbapi.cpv_exists(self._cpv)
-
- def is_in_overlay(self):
- ovl = self.get_overlay_path()
- return ovl != self._settings.settings["PORTDIR"] and str(ovl) != "0"
-
- def get_overlay_path (self):
- dir,ovl = self._settings.porttree.dbapi.findname2(self._cpv)
- return ovl
-
- def is_in_system (self):
- return (self._status != None)
-
- def is_missing_keyword(self):
- return self._status and "missing keyword" in self._status
-
- def is_testing(self, use_keywords = True):
- testArch = "~" + self.get_global_settings("ARCH")
- if not use_keywords: # keywords are NOT taken into account
- return testArch in self.get_package_settings("KEYWORDS").split()
-
- 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
- return self._status and testArch+" keyword" in self._status
- else:
- return status
-
- def is_masked (self, use_changed = True):
-
- if use_changed:
- 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:
- error(_("BUG in flags.new_masking_status. It returns \'%s\'"), status)
- else: # we have not touched the status
- return self._status and ("profile" in self._status or "package.mask" in self._status)
-
- else: # we want the original portage value XXX: bug if masked by user AND by system
-
- # get the normal masked ones
- if self._status and ("profile" in self._status or "package.mask" in self._status):
- return not flags.is_locally_masked(self, changes = False) # assume that if it is locally masked, it is not masked by the system
- else: # more difficult: get the ones we unmasked, but are masked by the system
- try:
- masked = self._settings.settings.pmaskdict[self.get_cp()]
- except KeyError: # key error: not masked
- return False
-
- for cpv in masked:
- if self.matches(cpv):
- return not flags.is_locally_masked(self, changes = False) # assume that if it is locally masked, it is not masked by the system
-
- return False
-
- def get_masking_reason(self):
- reason = portage.getmaskingreason(self.get_cpv(), settings = self._settings.settings)
-
- if reason:
- return reason.strip()
- else:
- return reason
-
- def get_iuse_flags (self, installed = False, removeForced = True):
- if not self.is_in_system():
- installed = True
-
- iuse = flags.filter_defaults(self.get_package_settings("IUSE", installed = installed).split())
-
- iuse = set(iuse)
-
- if removeForced:
- return list(iuse.difference(self.forced_flags))
- else:
- return list(iuse)
-
- def get_matched_dep_packages (self, depvar):
- # change the useflags, because we have internally changed some, but not made them visible for portage
- actual = self.get_actual_use_flags()
-
- depstring = ""
- try:
- for d in depvar:
- depstring += self.get_package_settings(d, installed = False)+" "
- except KeyError: # not found in porttree - use vartree
- depstring = ""
- for d in depvar:
- depstring += self.get_package_settings(d, installed = True)+" "
-
- deps = portage.dep_check(depstring, None, 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]
-
- return [d for d in deps if d[0] != "!"]
-
- def get_dep_packages (self, depvar = ["RDEPEND", "PDEPEND", "DEPEND"], with_criterions = False, return_blocks = False):
- dep_pkgs = [] # the package list
-
- # change the useflags, because we have internally changed some, but not made them visible for portage
- actual = self.get_actual_use_flags()
-
- depstring = ""
- for d in depvar:
- depstring += self.get_package_settings(d, installed = False)+" "
-
- # 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]
-
- def create_dep_pkgs_data (dep, pkg):
- """Returns the data to enter into the dep_pkgs list, which is either the package cpv or a tuple
- consisting of the cpv and the criterion."""
- if with_criterions:
- return (pkg.get_cpv(), dep)
- else:
- return pkg.get_cpv()
-
- for dep in deps:
- if dep[0] == '!': # blocking sth
- blocked = system.find_packages(dep, system.SET_INSTALLED)
- if len(blocked) == 1: # only exact one match allowed to be harmless
- if blocked[0].get_slot_cp() == self.get_slot_cp(): # blocks in the same slot are harmless
- continue
-
- if return_blocks:
- if with_criterions:
- dep_pkgs.append((dep, dep))
- else:
- dep_pkgs.append(dep)
- else:
- 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
- pkgs = system.find_packages(dep, masked = True)
- if not pkgs:
- raise PackageNotFoundException, dep
-
- pkgs = system.sort_package_list(pkgs)
- pkgs.reverse()
- done = False
- for p in pkgs:
- if not p.is_masked():
- dep_pkgs.append(create_dep_pkgs_data(dep, p))
- done = True
- break
- if not done:
- dep_pkgs.append(create_dep_pkgs_data(dep, pkgs[0]))
- else:
- dep_pkgs.append(create_dep_pkgs_data(dep, pkg))
-
- return dep_pkgs
-
- def get_global_settings(self, key, installed = True):
- with self._settingslock:
- self._init_settings(installed)
- v = self._settings.settings[key]
-
- return v
-
- def get_ebuild_path(self):
- if self.is_in_system():
- return self._settings.porttree.dbapi.findname(self._cpv)
- else:
- return self._settings.vartree.dbapi.findname(self._cpv)
-
- def get_files (self):
- if self.is_installed():
- path = os.path.join(self.get_global_settings("ROOT"), portage.VDB_PATH, self.get_cpv(), "CONTENTS")
- with open(path) as f:
- for line in f:
- yield line.split()[1].strip()
-
- def get_package_settings(self, var, installed = True):
- if installed and self.is_installed():
- mytree = self._settings.vartree
- else:
- mytree = self._settings.porttree
-
- r = mytree.dbapi.aux_get(self._cpv,[var])
-
- return r[0]
-
- def get_installed_use_flags(self):
- if self.is_installed():
- return self.get_package_settings("USE", installed = True).split()
- 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):
- return system.cpv_matches(self.get_cpv(), criterion)
+ """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._scpv = system.split_cpv(self._cpv)
+
+ if not self._scpv:
+ raise ValueError("invalid cpv: %s" % cpv)
+
+ self._settings = system.settings
+ self._settingslock = system.settings.settingslock
+ self._settings_installed = None
+
+ self._trees = system.settings.trees
+
+ self.forced_flags = set()
+
+ with self._settingslock:
+ self._init_settings(True)
+ 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
+
+ if self._status and len(self._status) == 1 and self._status[0] == "corrupted":
+ self._status = None
+
+ def _init_settings (self, installed):
+ inst = (installed and self.is_installed()) or (self.is_installed() and not self.is_in_system())
+
+ if self._settings_installed is not None and self._settings_installed != inst:
+ self._settings.settings.reset()
+
+ self._settings_installed = inst
+
+ if inst:
+ dbapi = self._settings.vartree.dbapi
+ else:
+ dbapi = self._settings.porttree.dbapi
+
+ self._settings.settings.setcpv(self.get_cpv(), mydb = dbapi)
+
+ def get_name(self):
+ return self._scpv[1]
+
+ def get_version(self):
+ v = self._scpv[2]
+ if self._scpv[3] != "r0":
+ v += "-" + self._scpv[3]
+ return v
+
+ def get_category(self):
+ return self._scpv[0]
+
+ def is_installed(self):
+ return self._settings.vartree.dbapi.cpv_exists(self._cpv)
+
+ def is_in_overlay(self):
+ ovl = self.get_overlay_path()
+ return ovl != self._settings.settings["PORTDIR"] and str(ovl) != "0"
+
+ def get_overlay_path (self):
+ dir,ovl = self._settings.porttree.dbapi.findname2(self._cpv)
+ return ovl
+
+ def is_in_system (self):
+ return (self._status != None)
+
+ def is_missing_keyword(self):
+ return self._status and "missing keyword" in self._status
+
+ def is_testing(self, use_keywords = True):
+ testArch = "~" + self.get_global_settings("ARCH")
+ if not use_keywords: # keywords are NOT taken into account
+ return testArch in self.get_package_settings("KEYWORDS").split()
+
+ 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
+ return self._status and testArch+" keyword" in self._status
+ else:
+ return status
+
+ def is_masked (self, use_changed = True):
+
+ if use_changed:
+ 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:
+ error(_("BUG in flags.new_masking_status. It returns \'%s\'"), status)
+ else: # we have not touched the status
+ return self._status and ("profile" in self._status or "package.mask" in self._status)
+
+ else: # we want the original portage value XXX: bug if masked by user AND by system
+
+ # get the normal masked ones
+ if self._status and ("profile" in self._status or "package.mask" in self._status):
+ return not flags.is_locally_masked(self, changes = False) # assume that if it is locally masked, it is not masked by the system
+ else: # more difficult: get the ones we unmasked, but are masked by the system
+ try:
+ masked = self._settings.settings.pmaskdict[self.get_cp()]
+ except KeyError: # key error: not masked
+ return False
+
+ for cpv in masked:
+ if self.matches(cpv):
+ return not flags.is_locally_masked(self, changes = False) # assume that if it is locally masked, it is not masked by the system
+
+ return False
+
+ def get_masking_reason(self):
+ reason = portage.getmaskingreason(self.get_cpv(), settings = self._settings.settings)
+
+ if reason:
+ return reason.strip()
+ else:
+ return reason
+
+ def get_iuse_flags (self, installed = False, removeForced = True):
+ if not self.is_in_system():
+ installed = True
+
+ iuse = flags.filter_defaults(self.get_package_settings("IUSE", installed = installed).split())
+
+ iuse = set(iuse)
+
+ if removeForced:
+ return list(iuse.difference(self.forced_flags))
+ else:
+ return list(iuse)
+
+ def get_matched_dep_packages (self, depvar):
+ # change the useflags, because we have internally changed some, but not made them visible for portage
+ actual = self.get_actual_use_flags()
+
+ depstring = ""
+ try:
+ for d in depvar:
+ depstring += self.get_package_settings(d, installed = False)+" "
+ except KeyError: # not found in porttree - use vartree
+ depstring = ""
+ for d in depvar:
+ depstring += self.get_package_settings(d, installed = True)+" "
+
+ deps = portage.dep_check(depstring, None, 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]
+
+ return [d for d in deps if d[0] != "!"]
+
+ def get_dep_packages (self, depvar = ["RDEPEND", "PDEPEND", "DEPEND"], with_criterions = False, return_blocks = False):
+ dep_pkgs = [] # the package list
+
+ # change the useflags, because we have internally changed some, but not made them visible for portage
+ actual = self.get_actual_use_flags()
+
+ depstring = ""
+ for d in depvar:
+ depstring += self.get_package_settings(d, installed = False)+" "
+
+ # 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]
+
+ def create_dep_pkgs_data (dep, pkg):
+ """Returns the data to enter into the dep_pkgs list, which is either the package cpv or a tuple
+ consisting of the cpv and the criterion."""
+ if with_criterions:
+ return (pkg.get_cpv(), dep)
+ else:
+ return pkg.get_cpv()
+
+ for dep in deps:
+ if dep[0] == '!': # blocking sth
+ blocked = system.find_packages(dep, system.SET_INSTALLED)
+ if len(blocked) == 1: # only exact one match allowed to be harmless
+ if blocked[0].get_slot_cp() == self.get_slot_cp(): # blocks in the same slot are harmless
+ continue
+
+ if return_blocks:
+ if with_criterions:
+ dep_pkgs.append((dep, dep))
+ else:
+ dep_pkgs.append(dep)
+ else:
+ 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
+ pkgs = system.find_packages(dep, masked = True)
+ if not pkgs:
+ raise PackageNotFoundException, dep
+
+ pkgs = system.sort_package_list(pkgs)
+ pkgs.reverse()
+ done = False
+ for p in pkgs:
+ if not p.is_masked():
+ dep_pkgs.append(create_dep_pkgs_data(dep, p))
+ done = True
+ break
+ if not done:
+ dep_pkgs.append(create_dep_pkgs_data(dep, pkgs[0]))
+ else:
+ dep_pkgs.append(create_dep_pkgs_data(dep, pkg))
+
+ return dep_pkgs
+
+ def get_global_settings(self, key, installed = True):
+ with self._settingslock:
+ self._init_settings(installed)
+ v = self._settings.settings[key]
+
+ return v
+
+ def get_ebuild_path(self):
+ if self.is_in_system():
+ return self._settings.porttree.dbapi.findname(self._cpv)
+ else:
+ return self._settings.vartree.dbapi.findname(self._cpv)
+
+ def get_files (self):
+ if self.is_installed():
+ path = os.path.join(self.get_global_settings("ROOT"), portage.VDB_PATH, self.get_cpv(), "CONTENTS")
+ with open(path) as f:
+ for line in f:
+ yield line.split()[1].strip()
+
+ def get_package_settings(self, var, installed = True):
+ if installed and self.is_installed():
+ mytree = self._settings.vartree
+ else:
+ mytree = self._settings.porttree
+
+ r = mytree.dbapi.aux_get(self._cpv,[var])
+
+ return r[0]
+
+ def get_installed_use_flags(self):
+ if self.is_installed():
+ return self.get_package_settings("USE", installed = True).split()
+ 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):
+ return system.cpv_matches(self.get_cpv(), criterion)
diff --git a/portato/backend/portage/package_22.py b/portato/backend/portage/package_22.py
index 4fe03d9..1dae1fe 100644
--- a/portato/backend/portage/package_22.py
+++ b/portato/backend/portage/package_22.py
@@ -15,8 +15,8 @@ from __future__ import absolute_import, with_statement
from .package import PortagePackage
class PortagePackage_22 (PortagePackage):
- """
- The 2.2 specialization of the portage package.
- Currently this is identical to the normal one.
- """
- pass
+ """
+ The 2.2 specialization of the portage package.
+ Currently this is identical to the normal one.
+ """
+ pass
diff --git a/portato/backend/portage/sets.py b/portato/backend/portage/sets.py
index 24ceaca..8d8ef28 100644
--- a/portato/backend/portage/sets.py
+++ b/portato/backend/portage/sets.py
@@ -17,130 +17,130 @@ import itertools as itt
import portage
try:
- import portage.dep as portage_dep
+ import portage.dep as portage_dep
except ImportError:
- import portage_dep
+ import portage_dep
from .. import system
from ...helper import debug
class Set(object):
- def get_pkgs(self, key, is_regexp, masked, with_version, only_cpv):
- raise NotImplementedError
+ def get_pkgs(self, key, is_regexp, masked, with_version, only_cpv):
+ raise NotImplementedError
- def find (self, key, masked = False, with_version = True, only_cpv = False):
- if key is None: key = ""
-
- is_regexp = key == "" or ("*" in key and key[0] not in ("*","=","<",">","~","!"))
+ def find (self, key, masked = False, with_version = True, only_cpv = False):
+ if key is None: key = ""
+
+ is_regexp = key == "" or ("*" in key and key[0] not in ("*","=","<",">","~","!"))
- try:
- t = self.get_pkgs(key, is_regexp, masked, with_version, only_cpv)
- # catch the "ambigous package" Exception
- except ValueError, e:
- if isinstance(e[0], list):
- t = set()
- for cp in e[0]:
- t.update(self.get_pkgs(cp, is_regexp, masked, with_version, only_cpv))
- else:
- raise
+ try:
+ t = self.get_pkgs(key, is_regexp, masked, with_version, only_cpv)
+ # catch the "ambigous package" Exception
+ except ValueError, e:
+ if isinstance(e[0], list):
+ t = set()
+ for cp in e[0]:
+ t.update(self.get_pkgs(cp, is_regexp, masked, with_version, only_cpv))
+ else:
+ raise
- return t
+ return t
class FilterSet (Set):
- def get_list(self):
- raise NotImplementedError
-
- def get_pkgs (self, key, is_regexp, masked, with_version, only_cpv):
- t = set()
- for pkg in self.get_list():
- if is_regexp:
- if not re.match(key, pkg, re.I): continue
+ def get_list(self):
+ raise NotImplementedError
+
+ def get_pkgs (self, key, is_regexp, masked, with_version, only_cpv):
+ t = set()
+ for pkg in self.get_list():
+ if is_regexp:
+ if not re.match(key, pkg, re.I): continue
- if not with_version:
- t.add(portage_dep.dep_getkey(pkg))
-
- t.add(system.find_best_match(pkg, only_cpv = True))
+ if not with_version:
+ t.add(portage_dep.dep_getkey(pkg))
+
+ t.add(system.find_best_match(pkg, only_cpv = True))
- return t
+ return t
class PortageSet (FilterSet):
- def __init__ (self, name):
- FilterSet.__init__(self)
- debug("Loading portage set '%s'", name)
- self.portageSet = system.settings.setsconfig.getSets()[name]
+ def __init__ (self, name):
+ FilterSet.__init__(self)
+ debug("Loading portage set '%s'", name)
+ self.portageSet = system.settings.setsconfig.getSets()[name]
- def get_list(self):
- return itt.imap(str, self.portageSet.getAtoms())
+ def get_list(self):
+ return itt.imap(str, self.portageSet.getAtoms())
class SystemSet (FilterSet):
- def get_list(self):
- for cp in system.settings.settings.packages:
- if cp[0] == "*": yield cp[1:]
+ def get_list(self):
+ for cp in system.settings.settings.packages:
+ if cp[0] == "*": yield cp[1:]
class WorldSet (FilterSet):
- def get_list(self):
- with open(portage.WORLD_FILE) as f:
- for cp in f:
- cp = cp.strip()
- if cp and cp[0] != "#":
- yield cp
+ def get_list(self):
+ with open(portage.WORLD_FILE) as f:
+ for cp in f:
+ cp = cp.strip()
+ if cp and cp[0] != "#":
+ yield cp
class InstalledSet (Set):
- def get_pkgs (self, key, is_regexp, masked, with_version, only_cpv):
- if is_regexp:
- if with_version:
- t = system.settings.vartree.dbapi.cpv_all()
- else:
- t = system.settings.vartree.dbapi.cp_all()
+ def get_pkgs (self, key, is_regexp, masked, with_version, only_cpv):
+ if is_regexp:
+ if with_version:
+ t = system.settings.vartree.dbapi.cpv_all()
+ else:
+ t = system.settings.vartree.dbapi.cp_all()
- if key:
- t = filter(lambda x: re.match(key, x, re.I), t)
+ if key:
+ t = filter(lambda x: re.match(key, x, re.I), t)
- return set(t)
- else:
- return set(system.settings.vartree.dbapi.match(key))
+ return set(t)
+ else:
+ return set(system.settings.vartree.dbapi.match(key))
class TreeSet (Set):
- def get_pkgs (self, key, is_regexp, masked, with_version, only_cpv):
- if is_regexp:
- if with_version:
- t = system.settings.porttree.dbapi.cpv_all()
- else:
- t = system.settings.porttree.dbapi.cp_all()
+ def get_pkgs (self, key, is_regexp, masked, with_version, only_cpv):
+ if is_regexp:
+ if with_version:
+ t = system.settings.porttree.dbapi.cpv_all()
+ else:
+ t = system.settings.porttree.dbapi.cp_all()
- if key:
- t = filter(lambda x: re.match(key, x, re.I), t)
+ if key:
+ t = filter(lambda x: re.match(key, x, re.I), t)
- elif masked:
- t = system.settings.porttree.dbapi.xmatch("match-all", key)
- else:
- t = system.settings.porttree.dbapi.match(key)
+ elif masked:
+ t = system.settings.porttree.dbapi.xmatch("match-all", key)
+ else:
+ t = system.settings.porttree.dbapi.match(key)
- return set(t)
+ return set(t)
class AllSet (Set):
-
- def __init__ (self):
- Set.__init__(self)
- self.tree = TreeSet()
- self.installed = InstalledSet()
+
+ def __init__ (self):
+ Set.__init__(self)
+ self.tree = TreeSet()
+ self.installed = InstalledSet()
- def find (self, *args, **kwargs):
- return self.tree.find(*args, **kwargs) | self.installed.find(*args, **kwargs)
+ def find (self, *args, **kwargs):
+ return self.tree.find(*args, **kwargs) | self.installed.find(*args, **kwargs)
class UninstalledSet (Set):
- def __init__ (self):
- Set.__init__(self)
- self.all = AllSet()
- self.installed = InstalledSet()
+ def __init__ (self):
+ Set.__init__(self)
+ self.all = AllSet()
+ self.installed = InstalledSet()
- def find (self, *args, **kwargs):
- return self.all.find(*args, **kwargs) - self.installed.find(*args, **kwargs)
+ def find (self, *args, **kwargs):
+ return self.all.find(*args, **kwargs) - self.installed.find(*args, **kwargs)
diff --git a/portato/backend/portage/settings.py b/portato/backend/portage/settings.py
index 5d466ad..0e7eccb 100644
--- a/portato/backend/portage/settings.py
+++ b/portato/backend/portage/settings.py
@@ -17,42 +17,42 @@ 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.trees = None
- 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=self.trees, **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 ...
+ """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.trees = None
+ 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=self.trees, **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/settings_22.py b/portato/backend/portage/settings_22.py
index a43d69e..5274b3b 100644
--- a/portato/backend/portage/settings_22.py
+++ b/portato/backend/portage/settings_22.py
@@ -16,12 +16,12 @@ import portage.sets
from .settings import PortageSettings
class PortageSettings_22 (PortageSettings):
- """Enhances the normal PortageSettings in ways, that it adds the setsconfig."""
+ """Enhances the normal PortageSettings in ways, that it adds the setsconfig."""
- def __init__ (self):
- PortageSettings.__init__(self)
+ def __init__ (self):
+ PortageSettings.__init__(self)
- def load (self):
- PortageSettings.load(self)
+ def load (self):
+ PortageSettings.load(self)
- self.setsconfig = portage.sets.load_default_config(self.settings, self.trees[self.settings["ROOT"]])
+ self.setsconfig = portage.sets.load_default_config(self.settings, self.trees[self.settings["ROOT"]])
diff --git a/portato/backend/portage/system.py b/portato/backend/portage/system.py
index 2394a10..e81951e 100644
--- a/portato/backend/portage/system.py
+++ b/portato/backend/portage/system.py
@@ -15,9 +15,9 @@ from __future__ import absolute_import, with_statement
import re, os, os.path
import portage
try:
- import portage.dep as portage_dep
+ import portage.dep as portage_dep
except ImportError:
- import portage_dep
+ import portage_dep
from collections import defaultdict
import itertools as itt
@@ -30,386 +30,386 @@ from ..system_interface import SystemInterface
from ...helper import debug, info, warning, unique_array
class PortageSystem (SystemInterface):
- """This class provides access to the portage-system."""
-
- # pre-compile the RE removing the ".svn" and "CVS" entries
- unwantedPkgsRE = re.compile(r".*(\.svn|CVS)$")
- withBdepsRE = re.compile(r"--with-bdeps\s*( |=)\s*y")
+ """This class provides access to the portage-system."""
+
+ # pre-compile the RE removing the ".svn" and "CVS" entries
+ unwantedPkgsRE = re.compile(r".*(\.svn|CVS)$")
+ withBdepsRE = re.compile(r"--with-bdeps\s*( |=)\s*y")
- def __init__ (self):
- """Constructor."""
- self.settings = PortageSettings()
- portage.WORLD_FILE = os.path.join(self.settings.settings["ROOT"],portage.WORLD_FILE)
-
- self.use_descs = {}
- self.local_use_descs = defaultdict(dict)
-
- self.setmap = {
- self.SET_ALL : syssets.AllSet,
- self.SET_INSTALLED : syssets.InstalledSet,
- self.SET_UNINSTALLED : syssets.UninstalledSet,
- self.SET_TREE : syssets.TreeSet,
- "world" : syssets.WorldSet,
- "system" : syssets.SystemSet
- }
-
- def has_set_support (self):
- return False
-
- def get_sets (self, description = False):
- if description:
- return (("world", "The world set."), ("system", "The system set."))
- else:
- return ("world", "system")
-
- def get_version (self):
- return "Portage %s" % portage.VERSION
-
- def new_package (self, cpv):
- return PortagePackage(cpv)
-
- def get_config_path (self):
- return portage.USER_CONFIG_PATH
-
- 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 get_environment (self):
- default_opts = self.get_global_settings("EMERGE_DEFAULT_OPTS")
- opts = dict(os.environ)
- opts.update(TERM = "xterm") # emulate terminal :)
- opts.update(PAGER = "less") # force less
-
- if default_opts:
- opt_list = default_opts.split()
- changed = False
-
- for option in ["--ask", "-a", "--pretend", "-p"]:
- if option in opt_list:
- opt_list.remove(option)
- changed = True
-
- if changed:
- opts.update(EMERGE_DEFAULT_OPTS = " ".join(opt_list))
-
- return opts
-
- def cpv_matches (self, cpv, criterion):
- if portage.match_from_list(criterion, [cpv]) == []:
- return False
- else:
- return True
-
- def with_bdeps(self):
- """Returns whether the "--with-bdeps" option is set to true.
-
- @returns: the value of --with-bdeps
- @rtype: boolean
- """
-
- settings = self.get_global_settings("EMERGE_DEFAULT_OPTS").split()
- for s in settings:
- if self.withBdepsRE.match(s):
- return True
-
- return False
-
- 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 or RE
- @returns:
- 1. None if no name is given
- 2. a lambda function
- @rtype: function
- """
-
- if name != None:
- if isinstance(name, str):
- return lambda x: re.match(".*"+name+".*",x, re.I)
- else: # assume regular expression
- return lambda x: name.match(x)
- else:
- return lambda x: True
-
- def geneticize_list (self, list_of_packages, only_cpv = False):
- """Convertes a list of cpv's into L{backend.Package}s.
-
- @param list_of_packages: the list of packages
- @type list_of_packages: string[]
- @param only_cpv: do nothing - return the passed list
- @type only_cpv: boolean
- @returns: converted list
- @rtype: PortagePackage[]
- """
-
- if not only_cpv:
- return [self.new_package(x) for x in list_of_packages]
- elif not isinstance(list_of_packages, list):
- return list(list_of_packages)
- else:
- return list_of_packages
-
- def get_global_settings (self, key):
- self.settings.settings.reset()
- return self.settings.settings[key]
-
- def find_best (self, list, only_cpv = False):
- if only_cpv:
- return portage.best(list)
- else:
- return self.new_package(portage.best(list))
-
- def find_best_match (self, search_key, masked = False, only_installed = False, only_cpv = False):
- t = []
-
- if not only_installed:
- pkgSet = self.SET_TREE
- else:
- pkgSet = self.SET_INSTALLED
-
- t = self.find_packages(search_key, pkgSet = pkgSet, masked = masked, with_version = True, only_cpv = True)
-
- if VERSION >= (2,1,5):
- t += [pkg.get_cpv() for pkg in self.find_packages(search_key, self.SET_INSTALLED) if not (pkg.is_testing(True) or pkg.is_masked())]
- elif not only_installed: # no need to run twice
- t += self.find_packages(search_key, self.SET_INSTALLED, only_cpv=True)
-
- if t:
- t = unique_array(t)
- return self.find_best(t, only_cpv)
-
- return None
-
- def _get_set (self, pkgSet):
- pkgSet = pkgSet.lower()
- if pkgSet == "": pkgSet = self.SET_ALL
-
- return self.setmap[pkgSet]()
-
- def find_packages (self, key = "", pkgSet = SystemInterface.SET_ALL, masked = False, with_version = True, only_cpv = False):
- return self.geneticize_list(self._get_set(pkgSet).find(key, masked, with_version, only_cpv), only_cpv or not with_version)
-
- 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(PortagePackage.compare_version) # XXX: waaah ... direct package naming... =/
- return pkglist
-
- def reload_settings (self):
- self.settings.load()
-
- def get_new_packages (self, packages):
- """Gets a list of packages and returns the best choice for each in the portage tree.
-
- @param packages: the list of packages
- @type packages: string[]
- @returns: the list of packages
- @rtype: backend.Package[]
- """
-
- new_packages = []
-
- def append(crit, best, inst):
- if not best:
- return
-
- if not best.is_installed() and (best.is_masked() or best.is_testing(True)): # check to not update unnecessairily
- for i in inst:
- if i.matches(crit):
- debug("The installed %s matches %s. Discarding upgrade to masked version.", i.get_cpv(), crit)
- return
-
- new_packages.append(best)
-
- for p in packages:
- inst = self.find_packages(p, self.SET_INSTALLED)
-
- best_p = self.find_best_match(p)
- if best_p is None:
- best_p = self.find_best_match(p, masked = True)
- if best_p is None:
- warning(_("No best match for %s. It seems not to be in the tree anymore.") % p)
- continue
- else:
- debug("Best match for %s is masked" % p)
-
- if len(inst) > 1:
- myslots = set()
- for i in inst: # get the slots of the installed packages
- myslots.add(i.get_package_settings("SLOT"))
-
- myslots.add(best_p.get_package_settings("SLOT")) # add the slot of the best package in portage
- for slot in myslots:
- crit = "%s:%s" % (p, slot)
- append(crit, self.find_best_match(crit), inst)
- else:
- append(p, best_p, inst)
-
- return new_packages
-
- def get_updated_packages (self):
- packages = self.get_new_packages(self.find_packages(pkgSet = self.SET_INSTALLED, with_version = False))
- packages = [x for x in packages if x is not None and not x.is_installed()]
- return packages
-
- def update_world (self, sets = ("world", "system"), newuse = False, deep = False):
- packages = set()
- map(packages.add, itt.chain(*[self.find_packages(pkgSet = s, with_version = False) for s in sets]))
-
- states = [(["RDEPEND", "PDEPEND"], True)]
- if self.with_bdeps():
- states.append((["DEPEND"], True))
-
- checked = []
- updating = []
- raw_checked = {}
- def check (p, add_not_installed = True, prev_appended = False):
- """Checks whether a package is updated or not."""
-
- if p.get_slot_cp() in checked:
- return
- else:
- if (not p.is_installed()) and (not add_not_installed):
- # don't add these packages to checked as we may see them again
- # - and then we might have add_not_installed being True
- return
- else:
- checked.append(p.get_slot_cp())
-
- appended = False
- tempDeep = False
-
- if not p.is_installed():
- oldList = self.find_packages(p.get_slot_cp(), self.SET_INSTALLED)
- 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_packages(p.get_cp(), self.SET_INSTALLED))
- if not oldList:
- info(_("Found a not installed dependency: %s.") % p.get_cpv())
- oldList = [p]
-
- 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_iuse_flags(installed = False)) # IUSE in the ebuild
- old_iuse = set(p.get_iuse_flags(installed = True)) # IUSE in the vardb
-
- # add forced flags, as they might trigger a rebuild
- new_iuse_f = set(p.get_iuse_flags(installed = False, removeForced = False))
- old_iuse_f = set(p.get_iuse_flags(installed = True, removeForced = False))
-
- if new_iuse.symmetric_difference(old_iuse): # difference between IUSE (w/o forced)
- tempDeep = True
- if not appended:
- updating.append((p,p))
- appended = True
-
- else: # check for difference between the _set_ useflags (w/ forced)
- if new_iuse_f.intersection(p.get_actual_use_flags()).symmetric_difference(old_iuse_f.intersection(p.get_installed_use_flags())):
- tempDeep = True
- if not appended:
- updating.append((p,p))
- appended = True
-
- if deep or tempDeep:
- if (appended or prev_appended) and len(states) < 2:
- real_states = states + [("PDEPEND", True), ("DEPEND", False)]
- else:
- real_states = states
- for state in real_states:
- for i in p.get_matched_dep_packages(state[0]):
- if i not in raw_checked or raw_checked[i] == False:
- raw_checked.update({i : state[1]})
- bm = self.get_new_packages([i])
- if not bm:
- warning(_("Bug? No best match could be found for '%(package)s'. Needed by: '%(cpv)s'."), {"package" : i, "cpv": p.get_cpv()})
- else:
- for pkg in bm:
- if not pkg: continue
- check(pkg, state[1], appended) # XXX: should be 'or'ed with prev_appended?
-
- for p in self.get_new_packages(packages):
- if not p: continue # if a masked package is installed we have "None" here
- check(p, True)
-
- return updating
-
- 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 not self.use_descs and not self.local_use_descs:
- for dir in [self.settings.settings["PORTDIR"]] + self.settings.settings["PORTDIR_OVERLAY"].split():
-
- # read use.desc
- try:
- f = open(os.path.join(dir, "profiles/use.desc"))
- for line in f:
- 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]
- except IOError:
- pass
- finally:
- f.close()
-
- # read use.local.desc
- try:
- f = open(os.path.join(dir, "profiles/use.local.desc"))
- for line in f:
- line = line.strip()
- if line and line[0] != '#':
- fields = [x.strip() for x in line.split(":",1)]
- if len(fields) == 2:
- subfields = [x.strip() for x in fields[1].split(" - ",1)]
- if len(subfields) == 2:
- self.local_use_descs[fields[0]].update([subfields])
- except IOError:
- pass
- finally:
- f.close()
-
- # start
- desc = self.use_descs.get(flag, "")
- if package is not None:
- if package in self.local_use_descs:
- desc = self.local_use_descs[package].get(flag, desc)
-
- return desc
+ def __init__ (self):
+ """Constructor."""
+ self.settings = PortageSettings()
+ portage.WORLD_FILE = os.path.join(self.settings.settings["ROOT"],portage.WORLD_FILE)
+
+ self.use_descs = {}
+ self.local_use_descs = defaultdict(dict)
+
+ self.setmap = {
+ self.SET_ALL : syssets.AllSet,
+ self.SET_INSTALLED : syssets.InstalledSet,
+ self.SET_UNINSTALLED : syssets.UninstalledSet,
+ self.SET_TREE : syssets.TreeSet,
+ "world" : syssets.WorldSet,
+ "system" : syssets.SystemSet
+ }
+
+ def has_set_support (self):
+ return False
+
+ def get_sets (self, description = False):
+ if description:
+ return (("world", "The world set."), ("system", "The system set."))
+ else:
+ return ("world", "system")
+
+ def get_version (self):
+ return "Portage %s" % portage.VERSION
+
+ def new_package (self, cpv):
+ return PortagePackage(cpv)
+
+ def get_config_path (self):
+ return portage.USER_CONFIG_PATH
+
+ 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 get_environment (self):
+ default_opts = self.get_global_settings("EMERGE_DEFAULT_OPTS")
+ opts = dict(os.environ)
+ opts.update(TERM = "xterm") # emulate terminal :)
+ opts.update(PAGER = "less") # force less
+
+ if default_opts:
+ opt_list = default_opts.split()
+ changed = False
+
+ for option in ["--ask", "-a", "--pretend", "-p"]:
+ if option in opt_list:
+ opt_list.remove(option)
+ changed = True
+
+ if changed:
+ opts.update(EMERGE_DEFAULT_OPTS = " ".join(opt_list))
+
+ return opts
+
+ def cpv_matches (self, cpv, criterion):
+ if portage.match_from_list(criterion, [cpv]) == []:
+ return False
+ else:
+ return True
+
+ def with_bdeps(self):
+ """Returns whether the "--with-bdeps" option is set to true.
+
+ @returns: the value of --with-bdeps
+ @rtype: boolean
+ """
+
+ settings = self.get_global_settings("EMERGE_DEFAULT_OPTS").split()
+ for s in settings:
+ if self.withBdepsRE.match(s):
+ return True
+
+ return False
+
+ 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 or RE
+ @returns:
+ 1. None if no name is given
+ 2. a lambda function
+ @rtype: function
+ """
+
+ if name != None:
+ if isinstance(name, str):
+ return lambda x: re.match(".*"+name+".*",x, re.I)
+ else: # assume regular expression
+ return lambda x: name.match(x)
+ else:
+ return lambda x: True
+
+ def geneticize_list (self, list_of_packages, only_cpv = False):
+ """Convertes a list of cpv's into L{backend.Package}s.
+
+ @param list_of_packages: the list of packages
+ @type list_of_packages: string[]
+ @param only_cpv: do nothing - return the passed list
+ @type only_cpv: boolean
+ @returns: converted list
+ @rtype: PortagePackage[]
+ """
+
+ if not only_cpv:
+ return [self.new_package(x) for x in list_of_packages]
+ elif not isinstance(list_of_packages, list):
+ return list(list_of_packages)
+ else:
+ return list_of_packages
+
+ def get_global_settings (self, key):
+ self.settings.settings.reset()
+ return self.settings.settings[key]
+
+ def find_best (self, list, only_cpv = False):
+ if only_cpv:
+ return portage.best(list)
+ else:
+ return self.new_package(portage.best(list))
+
+ def find_best_match (self, search_key, masked = False, only_installed = False, only_cpv = False):
+ t = []
+
+ if not only_installed:
+ pkgSet = self.SET_TREE
+ else:
+ pkgSet = self.SET_INSTALLED
+
+ t = self.find_packages(search_key, pkgSet = pkgSet, masked = masked, with_version = True, only_cpv = True)
+
+ if VERSION >= (2,1,5):
+ t += [pkg.get_cpv() for pkg in self.find_packages(search_key, self.SET_INSTALLED) if not (pkg.is_testing(True) or pkg.is_masked())]
+ elif not only_installed: # no need to run twice
+ t += self.find_packages(search_key, self.SET_INSTALLED, only_cpv=True)
+
+ if t:
+ t = unique_array(t)
+ return self.find_best(t, only_cpv)
+
+ return None
+
+ def _get_set (self, pkgSet):
+ pkgSet = pkgSet.lower()
+ if pkgSet == "": pkgSet = self.SET_ALL
+
+ return self.setmap[pkgSet]()
+
+ def find_packages (self, key = "", pkgSet = SystemInterface.SET_ALL, masked = False, with_version = True, only_cpv = False):
+ return self.geneticize_list(self._get_set(pkgSet).find(key, masked, with_version, only_cpv), only_cpv or not with_version)
+
+ 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(PortagePackage.compare_version) # XXX: waaah ... direct package naming... =/
+ return pkglist
+
+ def reload_settings (self):
+ self.settings.load()
+
+ def get_new_packages (self, packages):
+ """Gets a list of packages and returns the best choice for each in the portage tree.
+
+ @param packages: the list of packages
+ @type packages: string[]
+ @returns: the list of packages
+ @rtype: backend.Package[]
+ """
+
+ new_packages = []
+
+ def append(crit, best, inst):
+ if not best:
+ return
+
+ if not best.is_installed() and (best.is_masked() or best.is_testing(True)): # check to not update unnecessairily
+ for i in inst:
+ if i.matches(crit):
+ debug("The installed %s matches %s. Discarding upgrade to masked version.", i.get_cpv(), crit)
+ return
+
+ new_packages.append(best)
+
+ for p in packages:
+ inst = self.find_packages(p, self.SET_INSTALLED)
+
+ best_p = self.find_best_match(p)
+ if best_p is None:
+ best_p = self.find_best_match(p, masked = True)
+ if best_p is None:
+ warning(_("No best match for %s. It seems not to be in the tree anymore.") % p)
+ continue
+ else:
+ debug("Best match for %s is masked" % p)
+
+ if len(inst) > 1:
+ myslots = set()
+ for i in inst: # get the slots of the installed packages
+ myslots.add(i.get_package_settings("SLOT"))
+
+ myslots.add(best_p.get_package_settings("SLOT")) # add the slot of the best package in portage
+ for slot in myslots:
+ crit = "%s:%s" % (p, slot)
+ append(crit, self.find_best_match(crit), inst)
+ else:
+ append(p, best_p, inst)
+
+ return new_packages
+
+ def get_updated_packages (self):
+ packages = self.get_new_packages(self.find_packages(pkgSet = self.SET_INSTALLED, with_version = False))
+ packages = [x for x in packages if x is not None and not x.is_installed()]
+ return packages
+
+ def update_world (self, sets = ("world", "system"), newuse = False, deep = False):
+ packages = set()
+ map(packages.add, itt.chain(*[self.find_packages(pkgSet = s, with_version = False) for s in sets]))
+
+ states = [(["RDEPEND", "PDEPEND"], True)]
+ if self.with_bdeps():
+ states.append((["DEPEND"], True))
+
+ checked = []
+ updating = []
+ raw_checked = {}
+ def check (p, add_not_installed = True, prev_appended = False):
+ """Checks whether a package is updated or not."""
+
+ if p.get_slot_cp() in checked:
+ return
+ else:
+ if (not p.is_installed()) and (not add_not_installed):
+ # don't add these packages to checked as we may see them again
+ # - and then we might have add_not_installed being True
+ return
+ else:
+ checked.append(p.get_slot_cp())
+
+ appended = False
+ tempDeep = False
+
+ if not p.is_installed():
+ oldList = self.find_packages(p.get_slot_cp(), self.SET_INSTALLED)
+ 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_packages(p.get_cp(), self.SET_INSTALLED))
+ if not oldList:
+ info(_("Found a not installed dependency: %s.") % p.get_cpv())
+ oldList = [p]
+
+ 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_iuse_flags(installed = False)) # IUSE in the ebuild
+ old_iuse = set(p.get_iuse_flags(installed = True)) # IUSE in the vardb
+
+ # add forced flags, as they might trigger a rebuild
+ new_iuse_f = set(p.get_iuse_flags(installed = False, removeForced = False))
+ old_iuse_f = set(p.get_iuse_flags(installed = True, removeForced = False))
+
+ if new_iuse.symmetric_difference(old_iuse): # difference between IUSE (w/o forced)
+ tempDeep = True
+ if not appended:
+ updating.append((p,p))
+ appended = True
+
+ else: # check for difference between the _set_ useflags (w/ forced)
+ if new_iuse_f.intersection(p.get_actual_use_flags()).symmetric_difference(old_iuse_f.intersection(p.get_installed_use_flags())):
+ tempDeep = True
+ if not appended:
+ updating.append((p,p))
+ appended = True
+
+ if deep or tempDeep:
+ if (appended or prev_appended) and len(states) < 2:
+ real_states = states + [("PDEPEND", True), ("DEPEND", False)]
+ else:
+ real_states = states
+ for state in real_states:
+ for i in p.get_matched_dep_packages(state[0]):
+ if i not in raw_checked or raw_checked[i] == False:
+ raw_checked.update({i : state[1]})
+ bm = self.get_new_packages([i])
+ if not bm:
+ warning(_("Bug? No best match could be found for '%(package)s'. Needed by: '%(cpv)s'."), {"package" : i, "cpv": p.get_cpv()})
+ else:
+ for pkg in bm:
+ if not pkg: continue
+ check(pkg, state[1], appended) # XXX: should be 'or'ed with prev_appended?
+
+ for p in self.get_new_packages(packages):
+ if not p: continue # if a masked package is installed we have "None" here
+ check(p, True)
+
+ return updating
+
+ 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 not self.use_descs and not self.local_use_descs:
+ for dir in [self.settings.settings["PORTDIR"]] + self.settings.settings["PORTDIR_OVERLAY"].split():
+
+ # read use.desc
+ try:
+ f = open(os.path.join(dir, "profiles/use.desc"))
+ for line in f:
+ 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]
+ except IOError:
+ pass
+ finally:
+ f.close()
+
+ # read use.local.desc
+ try:
+ f = open(os.path.join(dir, "profiles/use.local.desc"))
+ for line in f:
+ line = line.strip()
+ if line and line[0] != '#':
+ fields = [x.strip() for x in line.split(":",1)]
+ if len(fields) == 2:
+ subfields = [x.strip() for x in fields[1].split(" - ",1)]
+ if len(subfields) == 2:
+ self.local_use_descs[fields[0]].update([subfields])
+ except IOError:
+ pass
+ finally:
+ f.close()
+
+ # start
+ desc = self.use_descs.get(flag, "")
+ if package is not None:
+ if package in self.local_use_descs:
+ desc = self.local_use_descs[package].get(flag, desc)
+
+ return desc
diff --git a/portato/backend/portage/system_22.py b/portato/backend/portage/system_22.py
index a329ab0..d5b605f 100644
--- a/portato/backend/portage/system_22.py
+++ b/portato/backend/portage/system_22.py
@@ -24,41 +24,41 @@ from . import sets as syssets
class PortageSystem_22 (PortageSystem):
- def __init__ (self):
- self.settings = PortageSettings_22()
- portage.WORLD_FILE = os.path.join(self.settings.settings["ROOT"],portage.WORLD_FILE)
+ def __init__ (self):
+ self.settings = PortageSettings_22()
+ portage.WORLD_FILE = os.path.join(self.settings.settings["ROOT"],portage.WORLD_FILE)
- self.use_descs = {}
- self.local_use_descs = defaultdict(dict)
+ self.use_descs = {}
+ self.local_use_descs = defaultdict(dict)
- self.setmap = {
- self.SET_ALL : syssets.AllSet,
- self.SET_INSTALLED : syssets.InstalledSet,
- self.SET_UNINSTALLED : syssets.UninstalledSet,
- self.SET_TREE : syssets.TreeSet
- }
+ self.setmap = {
+ self.SET_ALL : syssets.AllSet,
+ self.SET_INSTALLED : syssets.InstalledSet,
+ self.SET_UNINSTALLED : syssets.UninstalledSet,
+ self.SET_TREE : syssets.TreeSet
+ }
- def get_update_option (self):
- return ["--update", "--oneshot"] # --oneshot to not record the used sets in world file
+ def get_update_option (self):
+ return ["--update", "--oneshot"] # --oneshot to not record the used sets in world file
- def has_set_support (self):
- return True
+ def has_set_support (self):
+ return True
- def get_sets (self, description = False):
- if description:
- return ((name, set.description) for name, set in self.settings.setsconfig.getSets().iteritems())
- else:
- return tuple(self.settings.setsconfig.getSets())
+ def get_sets (self, description = False):
+ if description:
+ return ((name, set.description) for name, set in self.settings.setsconfig.getSets().iteritems())
+ else:
+ return tuple(self.settings.setsconfig.getSets())
- def _get_set (self, pkgSet):
- pkgSet = pkgSet.lower()
- if pkgSet == "": pkgSet = self.SET_ALL
+ def _get_set (self, pkgSet):
+ pkgSet = pkgSet.lower()
+ if pkgSet == "": pkgSet = self.SET_ALL
- s = self.setmap.get(pkgSet, None)
- if s is None:
- return syssets.PortageSet(pkgSet)
- else:
- return s()
+ s = self.setmap.get(pkgSet, None)
+ if s is None:
+ return syssets.PortageSet(pkgSet)
+ else:
+ return s()
- def new_package (self, cpv):
- return PortagePackage_22(cpv)
+ def new_package (self, cpv):
+ return PortagePackage_22(cpv)
diff --git a/portato/backend/system_interface.py b/portato/backend/system_interface.py
index 1cb0ed1..6f13042 100644
--- a/portato/backend/system_interface.py
+++ b/portato/backend/system_interface.py
@@ -11,282 +11,282 @@
# Written by René 'Necoro' Neumann <necoro@necoro.net>
class SystemInterface (object):
-
- SET_ALL = "__portato_all__"
- SET_TREE = "__portato_tree__"
- SET_INSTALLED = "__portato_installed__"
- SET_UNINSTALLED = "__portato_uninstalled__"
-
- def has_set_support (self):
- """Signals, whether this backend supports sets.
-
- @rtype: boolean
- """
- raise NotImplementedError
-
- def get_sets (self):
- """Returns all supported sets in tuples consisting of name and description.
- If sets aren't supported, at least "world" and "system" have to be returned.
-
- @rtype: iter(string, string)
- """
- raise NotImplementedError
-
- def get_version (self):
- """Returns the version of the used backend.
-
- @rtype: string
- """
- raise NotImplementedError
-
- def split_cpv (self, cpv):
- """Splits a cpv into all its parts.
-
- @param cpv: the cpv to split
- @type cpv: string
- @returns: the splitted cpv
- @rtype: string[]
- """
-
- raise NotImplementedError
-
- def cpv_matches (self, cpv, criterion):
- """Checks whether a cpv matches a specific criterion.
-
- @param cpv: cpv to check
- @type cpv: string
- @param criterion: criterion to check against
- @type criterion: string
- @returns: match result
- @rtype: boolean
- """
-
- raise NotImplementedError
-
- def find_best(self, list, only_cpv = False):
- """Returns the best package out of a list of packages.
-
- @param list: the list of packages to select from
- @type list: string[]
- @param only_cpv: do not return package but only the cpv
- @type only_cpv: boolean
-
- @returns: the best package
- @rtype: backend.Package or string
- """
-
- raise NotImplementedError
-
- def find_best_match (self, search_key, masked = False, only_installed = False, only_cpv = 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 masked: if True, also look for masked packages
- @type masked: boolean
- @param only_installed: if True, only installed packages are searched
- @type only_installed: boolean
- @param only_cpv: do not return package but only the cpv
- @type only_cpv: boolean
-
- @returns: the package found or None
- @rtype: backend.Package or string
- """
-
- raise NotImplementedError
-
- def find_packages (self, key, pkgSet = SET_ALL, masked = False, with_version = True, only_cpv = False):
- """This returns a list of packages matching the key.
- As key, it is allowed to use basic regexps (".*") and the normal package specs. But not a combination
- of them.
-
- @param key: the key to look for
- @type key: string
- @param all: the package set to use
- @type all: string
- @param masked: if True, also look for masked packages
- @type masked: boolean
- @param with_version: if True, return CPVs - else CP
- @type with_version: boolean
- @param only_cpv: do not return package but only the cpv. if with_version is False, this is ignored
- @type only_cpv: boolean
-
- @returns: list of found packages
- @rtype: backend.Package[] or string[]
- """
-
- raise NotImplementedError
-
- def list_categories (self, 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[]
- """
-
- raise NotImplementedError
-
- def sort_package_list(self, pkglist):
- """Sorts a package list in the same manner portage does.
-
- @param pkglist: list to sort
- @type pkglist: Packages[]
- """
-
- raise NotImplementedError
-
- def reload_settings (self):
- """Reloads portage."""
-
- raise NotImplementedError
-
- def update_world (self, 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 of the tuple (new_package, old_package)
- @rtype: (backend.Package, backend.Package)[]
- """
-
- raise NotImplementedError
-
- def get_updated_packages (self):
- """Returns the packages for which a newer package is available in the portage tree and installable (thus not masked).
- This differs from update_world as it takes all installed packages into account but ignores changed useflags.
-
- @returns: the list of new packages
- @rtype: backend.Package[]
- """
-
- raise NotImplementedError
-
- def get_use_desc (self, flag, package = None):
- """Returns the description of a specific useflag or None if no desc was found.
- If a package is given (in the <cat>/<name> 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
- """
-
- raise NotImplementedError
-
- def get_global_settings(self, key):
- """Returns the value of a global setting, i.e. ARCH, USE, ROOT, DISTDIR etc.
-
- @param key: the setting to return
- @type key: string
- @returns: the value of this setting
- @rtype: string
- """
+
+ SET_ALL = "__portato_all__"
+ SET_TREE = "__portato_tree__"
+ SET_INSTALLED = "__portato_installed__"
+ SET_UNINSTALLED = "__portato_uninstalled__"
+
+ def has_set_support (self):
+ """Signals, whether this backend supports sets.
+
+ @rtype: boolean
+ """
+ raise NotImplementedError
+
+ def get_sets (self):
+ """Returns all supported sets in tuples consisting of name and description.
+ If sets aren't supported, at least "world" and "system" have to be returned.
+
+ @rtype: iter(string, string)
+ """
+ raise NotImplementedError
+
+ def get_version (self):
+ """Returns the version of the used backend.
+
+ @rtype: string
+ """
+ raise NotImplementedError
+
+ def split_cpv (self, cpv):
+ """Splits a cpv into all its parts.
+
+ @param cpv: the cpv to split
+ @type cpv: string
+ @returns: the splitted cpv
+ @rtype: string[]
+ """
+
+ raise NotImplementedError
+
+ def cpv_matches (self, cpv, criterion):
+ """Checks whether a cpv matches a specific criterion.
+
+ @param cpv: cpv to check
+ @type cpv: string
+ @param criterion: criterion to check against
+ @type criterion: string
+ @returns: match result
+ @rtype: boolean
+ """
+
+ raise NotImplementedError
+
+ def find_best(self, list, only_cpv = False):
+ """Returns the best package out of a list of packages.
+
+ @param list: the list of packages to select from
+ @type list: string[]
+ @param only_cpv: do not return package but only the cpv
+ @type only_cpv: boolean
+
+ @returns: the best package
+ @rtype: backend.Package or string
+ """
+
+ raise NotImplementedError
+
+ def find_best_match (self, search_key, masked = False, only_installed = False, only_cpv = 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 masked: if True, also look for masked packages
+ @type masked: boolean
+ @param only_installed: if True, only installed packages are searched
+ @type only_installed: boolean
+ @param only_cpv: do not return package but only the cpv
+ @type only_cpv: boolean
+
+ @returns: the package found or None
+ @rtype: backend.Package or string
+ """
+
+ raise NotImplementedError
+
+ def find_packages (self, key, pkgSet = SET_ALL, masked = False, with_version = True, only_cpv = False):
+ """This returns a list of packages matching the key.
+ As key, it is allowed to use basic regexps (".*") and the normal package specs. But not a combination
+ of them.
+
+ @param key: the key to look for
+ @type key: string
+ @param all: the package set to use
+ @type all: string
+ @param masked: if True, also look for masked packages
+ @type masked: boolean
+ @param with_version: if True, return CPVs - else CP
+ @type with_version: boolean
+ @param only_cpv: do not return package but only the cpv. if with_version is False, this is ignored
+ @type only_cpv: boolean
+
+ @returns: list of found packages
+ @rtype: backend.Package[] or string[]
+ """
+
+ raise NotImplementedError
+
+ def list_categories (self, 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[]
+ """
+
+ raise NotImplementedError
+
+ def sort_package_list(self, pkglist):
+ """Sorts a package list in the same manner portage does.
+
+ @param pkglist: list to sort
+ @type pkglist: Packages[]
+ """
+
+ raise NotImplementedError
+
+ def reload_settings (self):
+ """Reloads portage."""
+
+ raise NotImplementedError
+
+ def update_world (self, 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 of the tuple (new_package, old_package)
+ @rtype: (backend.Package, backend.Package)[]
+ """
+
+ raise NotImplementedError
+
+ def get_updated_packages (self):
+ """Returns the packages for which a newer package is available in the portage tree and installable (thus not masked).
+ This differs from update_world as it takes all installed packages into account but ignores changed useflags.
+
+ @returns: the list of new packages
+ @rtype: backend.Package[]
+ """
+
+ raise NotImplementedError
+
+ def get_use_desc (self, flag, package = None):
+ """Returns the description of a specific useflag or None if no desc was found.
+ If a package is given (in the <cat>/<name> 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
+ """
+
+ raise NotImplementedError
+
+ def get_global_settings(self, key):
+ """Returns the value of a global setting, i.e. ARCH, USE, ROOT, DISTDIR etc.
+
+ @param key: the setting to return
+ @type key: string
+ @returns: the value of this setting
+ @rtype: string
+ """
- raise NotImplementedError
+ raise NotImplementedError
- def new_package (self, cpv):
- """Returns an instance of the appropriate Package-Subclass.
+ def new_package (self, cpv):
+ """Returns an instance of the appropriate Package-Subclass.
- @param cpv: the cpv to create the package from
- @type cpv: string
- @returns: a new Package-object.
- @rtype: Package
- """
+ @param cpv: the cpv to create the package from
+ @type cpv: string
+ @returns: a new Package-object.
+ @rtype: Package
+ """
- raise NotImplementedError
+ raise NotImplementedError
- def get_config_path (self):
- """Returns the actual path to the config files.
-
- @returns: the path, e.g. /etc/portage
- @rtype: string
- """
+ def get_config_path (self):
+ """Returns the actual path to the config files.
+
+ @returns: the path, e.g. /etc/portage
+ @rtype: string
+ """
- raise NotImplementedError
+ raise NotImplementedError
- def get_sync_command (self):
- """Returns the command(s) to run for syncing. This can be overridden by the user.
+ def get_sync_command (self):
+ """Returns the command(s) to run for syncing. This can be overridden by the user.
- @returns: command to run
- @rtype: string[]
- """
+ @returns: command to run
+ @rtype: string[]
+ """
- raise NotImplementedError
+ raise NotImplementedError
- def get_merge_command (self):
- """Returns the command(s) to run for the merging.
+ def get_merge_command (self):
+ """Returns the command(s) to run for the merging.
- @returns: command to run
- @rtype: string[]
- """
+ @returns: command to run
+ @rtype: string[]
+ """
- raise NotImplementedError
+ raise NotImplementedError
- def get_oneshot_option (self):
- """Returns the options to append for marking a merge as "oneshot".
+ def get_oneshot_option (self):
+ """Returns the options to append for marking a merge as "oneshot".
- @returns: option(s) to append
- @rtype: string[]
- """
+ @returns: option(s) to append
+ @rtype: string[]
+ """
- raise NotImplementedError
+ raise NotImplementedError
- def get_newuse_option (self):
- """Returns the options to append for marking a merge as "newuse".
+ def get_newuse_option (self):
+ """Returns the options to append for marking a merge as "newuse".
- @returns: option(s) to append
- @rtype: string[]
- """
+ @returns: option(s) to append
+ @rtype: string[]
+ """
- raise NotImplementedError
+ raise NotImplementedError
- def get_deep_option (self):
- """Returns the options to append for marking a merge as "deep".
+ def get_deep_option (self):
+ """Returns the options to append for marking a merge as "deep".
- @returns: option(s) to append
- @rtype: string[]
- """
+ @returns: option(s) to append
+ @rtype: string[]
+ """
- raise NotImplementedError
+ raise NotImplementedError
- def get_update_option (self):
- """Returns the options to append for marking a merge as "update".
+ def get_update_option (self):
+ """Returns the options to append for marking a merge as "update".
- @returns: option(s) to append
- @rtype: string[]
- """
+ @returns: option(s) to append
+ @rtype: string[]
+ """
- raise NotImplementedError
+ raise NotImplementedError
- def get_pretend_option (self):
- """Returns the options to append for marking a merge as "pretend".
+ def get_pretend_option (self):
+ """Returns the options to append for marking a merge as "pretend".
- @returns: option(s) to append
- @rtype: string[]
- """
+ @returns: option(s) to append
+ @rtype: string[]
+ """
- raise NotImplementedError
+ raise NotImplementedError
- def get_unmerge_option (self):
- """Returns the options to append for marking a merge as "unmerge".
+ def get_unmerge_option (self):
+ """Returns the options to append for marking a merge as "unmerge".
- @returns: option(s) to append
- @rtype: string[]
- """
+ @returns: option(s) to append
+ @rtype: string[]
+ """
- raise NotImplementedError
+ raise NotImplementedError
- def get_environment (self):
- """Returns a dictionary of environment variables to set prior to do an emerge.
+ def get_environment (self):
+ """Returns a dictionary of environment variables to set prior to do an emerge.
- @returns: environment variables
- @rtype: dict{string : string}
- """
+ @returns: environment variables
+ @rtype: dict{string : string}
+ """
- raise NotImplementedError
+ raise NotImplementedError