summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--geneticone/gui/main.py151
-rw-r--r--geneticone/helper.py3
-rw-r--r--geneticone/package.py287
3 files changed, 271 insertions, 170 deletions
diff --git a/geneticone/gui/main.py b/geneticone/gui/main.py
index e0dceef..b533e11 100644
--- a/geneticone/gui/main.py
+++ b/geneticone/gui/main.py
@@ -41,11 +41,11 @@ class EmergeQueue:
def __init__ (self, tree = None, console = None, packages = None):
"""Constructor.
- @param tree: Tree to append all the items to.
+ @param tree: Tree to append all the items to. Default: None.
@type tree: gtk.TreeStore
- @param console: Output is shown here.
+ @param console: Output is shown here. Default: None
@type console: vte.Terminal
- @param packages: The list of packages sorted by categories. We will delete the appropriate category if we updated sth.
+ @param packages: The list of packages sorted by categories. We will delete the appropriate category if we updated sth. Default: None
@type packages: dictionary: {category: list_of_packages}."""
self.mergequeue = []
@@ -56,111 +56,165 @@ class EmergeQueue:
self.console = console
self.packages = packages
- if self.tree:
+ if self.tree:
self.emergeIt = self.tree.append(None, ["Emerge"])
self.unmergeIt = self.tree.append(None, ["Unmerge"])
else:
self.emergeIt = self.unmergeIt = None
def update_tree (self, it, cpv):
- try:
+ """This updates the tree recursivly.
+
+ @param it: iterator where to append
+ @type it: gtk.TreeIter
+ @param cpv: The package to append.
+ @type cpv: string (cat/pkg-ver)
+
+ @raise geneticone.BlockedException: When occured during dependency-calculation."""
+
+ # get depencies
+ if cpv in self.deps:
deps = self.deps[cpv]
- except KeyError:
+ else:
deps = geneticone.find_packages("="+cpv)[0].get_dep_packages()
self.deps.update({cpv : deps})
subIt = self.tree.append(it, [cpv])
+ # recursive call
for d in deps:
try:
self.update_tree(subIt, d)
except geneticone.BlockedException, e:
+ # remove the project
while self.tree.iter_parent(subIt):
subIt = self.tree.iter_parent(subIt)
self.remove_children(subIt)
raise e
+ # add iter
self.iters.update({cpv: subIt})
- def append (self, sth, unmerge = False, update = False):
+ def append (self, cpv, unmerge = False, update = False):
"""Appends a cpv either to the merge queue or to the unmerge-queue.
- Also update the tree-view."""
+ Also updates the tree-view.
+
+ @param cpv: Package to add
+ @type cpv: string (cat/pkg-ver)
+ @param unmerge: Set to True if you want to unmerge this package - else False. Default: False
+ @type unmerge: boolean
+ @param update: Set to True if a package is going to be updated (e.g. if the use-flags changed). Default: False
+ @type update: boolean"""
+
if not unmerge:
try:
# insert dependencies
- pkg = geneticone.find_packages("="+sth)[0]
+ pkg = geneticone.find_packages("="+cpv)[0]
deps = pkg.get_dep_packages()
if update:
- if deps == self.deps[sth]:
- return
+ if deps == self.deps[cpv]:
+ return # nothing changed - return
else:
- parentIt = self.tree.iter_parent(self.iters[sth])
- self.remove(self.iters[sth])
- self.deps.update({sth: deps})
- self.update_tree(parentIt, sth)
- else:
- self.mergequeue.append(sth)
- self.deps.update({sth : deps})
-
- # update tree
- if self.emergeIt:
- self.update_tree(self.emergeIt, sth)
+ parentIt = self.tree.iter_parent(self.iters[cpv])
+ self.remove(self.iters[cpv])
+ self.deps.update({cpv: deps})
+ self.update_tree(parentIt, cpv)
+ else: # not update
+ self.mergequeue.append(cpv)
+ self.deps.update({cpv : deps})
+ if self.emergeIt: self.update_tree(self.emergeIt, cpv)
- except geneticone.BlockedException, e :
+ except geneticone.BlockedException, e : # there is sth blocked --> call blocked_dialog
blocks = e[0]
- blocked_dialog(sth, blocks)
+ blocked_dialog(cpv, blocks)
return
- else:
- self.unmergequeue.append(sth)
+ else: # unmerge
+ self.unmergequeue.append(cpv)
if self.unmergeIt: # update tree
- self.tree.append(self.unmergeIt, [sth])
+ self.tree.append(self.unmergeIt, [cpv])
- def update_packages(self, process, packages):
- """This updates the packages-list. It simply removes all affected categories so they have to be rebuilt."""
- process.wait()
+ def _update_packages(self, packages, process = None):
+ """This updates the packages-list. It simply removes all affected categories so they have to be rebuilt.
+
+ @param packages: The packages which we emerged.
+ @type packages: list of cpvs
+ @param process: The process we have to wait for before we can do our work. Default: None.
+ @type process: subprocess.Popen"""
+
+ if process: process.wait()
for p in packages:
try:
- cat = geneticone.split_package_name(p)[0]
+ cat = geneticone.split_package_name(p)[0] # get category
while cat[0] in ["=",">","<","!"]:
cat = cat[1:]
- print cat,
+ print "Category: "+cat ,
del self.packages[cat]
- print "deleted"
- except KeyError:
+ print "marked for refreshing"
+ except KeyError: # not in self.packages - ignore
pass
def _emerge (self, options, packages, it):
- """Calls emerge and updates the terminal."""
+ """Calls emerge and updates the terminal.
+
+ @param options: options to send to emerge
+ @type options: list
+ @param packages: packages to emerge
+ @type packages: list
+ @param it: Iterator which points to an entry whose children will be removed after completion.
+ @type it: gtk.TreeIter"""
+
+ # open tty
(master, slave) = pty.openpty()
self.console.set_pty(master)
+
+ # start emerge
process = Popen(["/usr/bin/python","/usr/bin/emerge"]+options+packages, stdout = slave, stderr = STDOUT, shell = False)
- Thread(target=self.update_packages, args=(process, packages)).start()
+ Thread(target=self._update_packages, args=(packages, process)).start()
+
+ # remove
self.remove_children(it)
def emerge (self, force = False):
- """Emerges everything in the merge-queue. If force is 'False' (default) only 'emerge -pv' is called."""
- if len(self.mergequeue) == 0: return
+ """Emerges everything in the merge-queue.
+
+ @param force: If False, '-pv' is send to emerge. Default: False.
+ @type force: boolean"""
+ if len(self.mergequeue) == 0: return # nothing in queue
+
+ # prepare package-list
list = []
for k in self.mergequeue:
list += ["="+k]
s = []
if not force: s = ["-pv"]
+
self._emerge(s, list, self.emergeIt)
def unmerge (self, force = False):
- """Unmerges everything in the umerge-queue. If force is 'False' (default) only "emerge -pv -C" is called."""
- if len(self.unmergequeue) == 0: return
+ """Unmerges everything in the umerge-queue.
- list = self.unmergequeue[:]
+ @param force: If False, '-pv' is send to emerge. Default: False.
+ @type force: boolean"""
+
+ if len(self.unmergequeue) == 0: return # nothing in queue
+
+ list = self.unmergequeue[:] # copy the unmerge-queue
+
+ # set options
s = ["-C"]
if not force: s = ["-Cpv"]
+
self._emerge(s,list, self.unmergeIt)
def remove_children (self, parentIt):
- """Removes all children of a given parent TreeIter."""
+ """Removes all children of a given parent TreeIter.
+
+ @param parentIt: The iter from which to remove all children.
+ @type parentIt: gtk.TreeIter"""
+
childIt = self.tree.iter_children(parentIt)
while childIt:
@@ -169,18 +223,23 @@ class EmergeQueue:
self.remove(temp)
def remove (self, it):
- """Removes a specific item in the tree."""
+ """Removes a specific item in the tree. This does not remove the top-entries.
+
+ @param it: Iterator which points to the entry we are going to remove.
+ @type it: gtk.TreeIter"""
+
if self.tree.iter_parent(it): # NEVER remove our top stuff
cpv = self.tree.get_value(it,0)
- if self.tree.get_string_from_iter(it).split(":")[0] == self.tree.get_string_from_iter(self.emergeIt):
+ if self.tree.get_string_from_iter(it).split(":")[0] == self.tree.get_string_from_iter(self.emergeIt): # in Emerge
try:
self.mergequeue.remove(cpv)
del self.iters[cpv]
del self.deps[cpv]
- except ValueError:
+ except ValueError: # this is a dependency - ignore
pass
flags.remove_new_use_flags(cpv)
- else:
+
+ else: # in Unmerge
self.unmergequeue.remove(cpv)
self.tree.remove(it)
diff --git a/geneticone/helper.py b/geneticone/helper.py
index e59ca98..e97568b 100644
--- a/geneticone/helper.py
+++ b/geneticone/helper.py
@@ -27,6 +27,9 @@ class BlockedException (Exception):
class PackageNotFoundException (Exception):
pass
+class DependencyCalcError (Exception):
+ pass
+
def find_lambda (name):
"""Returns the function needed by all the find_all_*-functions. Returns None if no name is given."""
if name != None:
diff --git a/geneticone/package.py b/geneticone/package.py
index 9df92c7..085d4c2 100644
--- a/geneticone/package.py
+++ b/geneticone/package.py
@@ -20,22 +20,26 @@ import portage
from portage_util import unique_array
class Package (gentoolkit.Package):
- """This is just a subclass of the Package-class of gentoolkit."""
+ """This is a subclass of the gentoolkit.Package-class which a lot of additional functionality we need in Genetic/One."""
def __init__ (self, cpv):
+ """Constructor.
+
+ @param cpv: The cpv or gentoolkit.Package which describes the package to create.
+ @type cpv: string (cat/pkg-ver) or gentoolkit.Package-object."""
+
if isinstance(cpv, gentoolkit.Package):
cpv = cpv.get_cpv()
gentoolkit.Package.__init__(self, cpv)
def get_mask_status(self):
- '''gets the numeric mask status of a package
- can be translated as string:
- maskmodes = [ " ", " ~", " -", "M ", "M~", "M-" ]
- (0=unmasked 1=~arch 2=-arch etc.)
-
+ """Gets the numeric mask status of a package. The return value can be translated as a string when taking the following list of modes: [ " ", " ~", " -", "M ", "M~", "M-" ]
+
This method adapted from equery 0.1.4
Original author: Karl Trygve Kalleberg <karltk@gentoo.org>
- '''
+
+ @returns: mask status
+ @rtype: int"""
pkgmask = 0
if self.is_masked():
@@ -47,15 +51,19 @@ class Package (gentoolkit.Package):
pkgmask = pkgmask + 2
return pkgmask
- def get_size (self):
- return self.size()
-
def get_all_use_flags (self):
- """Returns a list of _all_ useflags for this package."""
+ """Returns a list of _all_ useflags for this package, i.e. all useflags you can set for this package.
+
+ @returns: list of use-flags
+ @rtype: list"""
+
return unique_array(self.get_env_var("IUSE").split())
def get_installed_use_flags (self):
- """Returns a list of the useflags enabled at installation time. If package is not installed, it returns an empty list."""
+ """Returns a list of the useflags enabled at installation time. If package is not installed, it returns an empty list.
+
+ @returns: list of useflags enabled at installation time or an empty list
+ @rtype: list"""
if self.is_installed():
uses = self.get_use_flags().split()
iuses = self.get_all_use_flags()
@@ -68,9 +76,18 @@ class Package (gentoolkit.Package):
return []
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: list"""
return flags.get_new_use_flags(self)
def get_actual_use_flags (self):
+ """This returns the result of installed_use_flags + new_use_flags. If the package is not installed, it returns only the new flags.
+
+ @return: list of flags
+ @rtype: list"""
+
if self.is_installed():
i_flags = self.get_installed_use_flags()
for f in self.get_new_use_flags():
@@ -83,19 +100,25 @@ class Package (gentoolkit.Package):
return self.get_new_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 get_all_deps (self):
- """Returns a linearised list of all first-level dependencies for this package, on
- the form [(comparator, [use flags], cpv), ...]"""
- return unique_array(self.get_compiletime_deps()+self.get_runtime_deps()+self.get_postmerge_deps())
-
def get_dep_packages (self):
- """Returns a cpv-list of packages on which this package depends and which have not been installed yet.
- raises: BlockedException, PackageNotFoundException."""
+ """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.
+
+ @returns: list of cpvs on which the package depend
+ @rtype: list
+ @raises geneticone.BlockedException: when a package in the dependency-list is blocked by an installed one
+ @raises geneticone.PackageNotFoundException: when a package in the dependency list could not be found in the system
+ @raises geneticone.DependencyCalcError: when an error occured during executing portage.dep_check()"""
+
dep_pkgs = [] # the package list
# check whether we got use-flags which are not visible for portage yet
@@ -116,10 +139,13 @@ class Package (gentoolkit.Package):
if not deps: # what is the difference to [1, []] ?
return []
+ if deps[0] == 0: # error
+ raise DependencyCalcError, deps[1]
+
deps = deps[1]
for dep in deps:
- if dep[0] == '!':
+ if dep[0] == '!': # blocking sth
blocked = find_installed_packages(dep[1:])
if blocked != []:
raise BlockedException, blocked[0].get_cpv()
@@ -134,67 +160,16 @@ class Package (gentoolkit.Package):
return dep_pkgs
- def own_get_dep_packages (self, old_cpv_dict = {}):
- # XXX: after having finished this, i realized, that there is already a portage function -.- ;
- # will keep this in case portage changes anything
- """Returns a list of all packages (i.e. package-cpvs) which this package depends on and which not have been installed yet.
- Param old_cpv_dict is a {cp: version}-dictionary holding already found deps.
- Raises a BlockedException if the package is being blocked by another installed package."""
- # XXX: This won't find blocking dependencies
- # XXX: Has some problems with modular X (this has a very strange ebuild) ... we should enhance _parse_deps
- print "Actual: "+self._cpv # debug output
-
- uses = [] # list of actual useflags / useflags the package has been installed with
- dep_packages = [] # list of packages returned
- dep_cpv_dict = {} # all dependencies are inserted here
-
- # get useflags
- if self.is_installed():
- uses = self.get_installed_use_flags()
- else:
- uses = self.get_settings("USE")
-
- # cycle through dependencies
- for (comp, flags, dep_cpv) in self.get_all_deps():
-
- # find blocking packages
- if comp and comp[0] == '!':
- blocked = find_installed_packages(comp[1:]+dep_cpv)
- if blocked != []:
- raise BlockedException, blocked[0].get_cpv()
- else: # next flag
- continue
-
- # look whether this package is really required
- needDep = True
- for flag in flags:
- if (flag[0] == '!' and flag[1:] in uses) or (flag[0] != '!' and flag not in uses):
- needDep = False
- break
-
- if needDep: # it is ...
- if find_installed_packages(comp+dep_cpv) == []: # ... and not installed yet
- d = find_best_match(comp+dep_cpv)
- if not d: # no package found
- raise PackageNotFoundException, dep_cpv
- if d.get_cp() not in old_cpv_dict: # ... and not found already by an other package
- dep_cpv_dict[d.get_cp()] = d.get_version()
- print "Dep: "+d.get_cpv() # debug
- dep_packages.append(d.get_cpv())
-
- for dep in dep_packages: # find dependencies for each package
- old_cpv_dict.update(dep_cpv_dict)
- old_cpv_dict.update({self.get_cp() : self.get_version()})
- dep_packages += find_packages("="+dep)[0].own_get_dep_packages(old_cpv_dict)
-
- return unique_array(dep_packages)
-
def get_cp (self):
- """Returns category/package."""
+ """Returns the cp-string.
+ @returns: category/package.
+ @rtype: string"""
return self.get_category()+"/"+self.get_name()
def is_masked (self):
- """Returns True if either masked by package.mask or by profile."""
+ """Returns True if either masked by package.mask or by profile.
+ @returns: mask-status
+ @rtype: boolean"""
# XXX: Better solution than string comparison?
status = portage.getmaskingstatus(self._cpv)
if "profile" in status or "package.mask" in status:
@@ -202,55 +177,119 @@ class Package (gentoolkit.Package):
return False
def matches (self, criterion):
- """This checks, whether this package matches a specific verisioning criterion - e.g.: "<=net-im/foobar-1.2"."""
+ """This checks, whether this package matches a specific verisioning criterion - e.g.: "<=net-im/foobar-1.2".
+ @param criterion: the criterion to match against
+ @type criterion: string"""
if portage.match_from_list(criterion, [self.get_cpv()]) == []:
return False
else:
return True
+#
+# OBSOLETE DEPENDENCY-CALCULATION-METHODS - kept in the case the above ones do not work
+#
+
+ #def own_get_dep_packages (self, old_cpv_dict = {}):
+ # # XXX: after having finished this, i realized, that there is already a portage function -.- ;
+ # """Returns a list of all packages (i.e. package-cpvs) which this package depends on and which not have been installed yet.
+ # Param old_cpv_dict is a {cp: version}-dictionary holding already found deps.
+ # Raises a BlockedException if the package is being blocked by another installed package."""
+ # # XXX: This won't find blocking dependencies
+ # # XXX: Has some problems with modular X (this has a very strange ebuild) ... we should enhance _parse_deps
+ # print "Actual: "+self._cpv # debug output
+ #
+ # uses = [] # list of actual useflags / useflags the package has been installed with
+ # dep_packages = [] # list of packages returned
+ # dep_cpv_dict = {} # all dependencies are inserted here
+ #
+ # # get useflags
+ # if self.is_installed():
+ # uses = self.get_installed_use_flags()
+ # else:
+ # uses = self.get_settings("USE")
+ #
+ # # cycle through dependencies
+ # for (comp, flags, dep_cpv) in self.get_all_deps():
+
+ # # find blocking packages
+ # if comp and comp[0] == '!':
+ # blocked = find_installed_packages(comp[1:]+dep_cpv)
+ # if blocked != []:
+ # raise BlockedException, blocked[0].get_cpv()
+ # else: # next flag
+ # continue
+ #
+ # # look whether this package is really required
+ # needDep = True
+ # for flag in flags:
+ # if (flag[0] == '!' and flag[1:] in uses) or (flag[0] != '!' and flag not in uses):
+ # needDep = False
+ # break
+
+ # if needDep: # it is ...
+ # if find_installed_packages(comp+dep_cpv) == []: # ... and not installed yet
+ # d = find_best_match(comp+dep_cpv)
+ # if not d: # no package found
+ # raise PackageNotFoundException, dep_cpv
+ # if d.get_cp() not in old_cpv_dict: # ... and not found already by an other package
+ # dep_cpv_dict[d.get_cp()] = d.get_version()
+ # print "Dep: "+d.get_cpv() # debug
+ # dep_packages.append(d.get_cpv())
+ #
+ # for dep in dep_packages: # find dependencies for each package
+ # old_cpv_dict.update(dep_cpv_dict)
+ # old_cpv_dict.update({self.get_cp() : self.get_version()})
+ # dep_packages += find_packages("="+dep)[0].own_get_dep_packages(old_cpv_dict)
+
+ # return unique_array(dep_packages)
+
+ #def get_all_deps (self):
+ # """Returns a linearised list of all first-level dependencies for this package, on
+ # the form [(comparator, [use flags], cpv), ...]"""
+ # return unique_array(self.get_compiletime_deps()+self.get_runtime_deps()+self.get_postmerge_deps())
- def _parse_deps(self,deps,curuse=[],level=0):
- """Modified method "_parse_deps" of gentoolkit.Package.
- Do NOT ignore blocks."""
- # store (comparator, [use predicates], cpv)
- r = []
- comparators = ["~","<",">","=","<=",">="]
- end = len(deps)
- i = 0
- while i < end:
- blocked = False
- tok = deps[i]
- if tok == ')':
- return r,i
- if tok[-1] == "?":
- tok = tok.replace("?","")
- sr,l = self._parse_deps(deps[i+2:],curuse=curuse+[tok],level=level+1)
- r += sr
- i += l + 3
- continue
- if tok == "||":
- sr,l = self._parse_deps(deps[i+2:],curuse,level=level+1)
- r += sr
- i += l + 3
- continue
- # conjonction, like in "|| ( ( foo bar ) baz )" => recurse
- if tok == "(":
- sr,l = self._parse_deps(deps[i+1:],curuse,level=level+1)
- r += sr
- i += l + 2
- continue
- # pkg block "!foo/bar" => ignore it
- if tok[0] == "!":
- #i += 1
- #continue
- blocked = True # added
- tok = tok[1:] # added
- # pick out comparator, if any
- cmp = ""
- for c in comparators:
- if tok.find(c) == 0:
- cmp = c
- if blocked: cmp = "!"+cmp # added
- tok = tok[len(cmp):]
- r.append((cmp,curuse,tok))
- i += 1
- return r,i
+ #def _parse_deps(self,deps,curuse=[],level=0):
+ # """Modified method "_parse_deps" of gentoolkit.Package.
+ # Do NOT ignore blocks."""
+ # # store (comparator, [use predicates], cpv)
+ # r = []
+ # comparators = ["~","<",">","=","<=",">="]
+ # end = len(deps)
+ # i = 0
+ # while i < end:
+ # blocked = False
+ # tok = deps[i]
+ # if tok == ')':
+ # return r,i
+ # if tok[-1] == "?":
+ # tok = tok.replace("?","")
+ # sr,l = self._parse_deps(deps[i+2:],curuse=curuse+[tok],level=level+1)
+ # r += sr
+ # i += l + 3
+ # continue
+ # if tok == "||":
+ # sr,l = self._parse_deps(deps[i+2:],curuse,level=level+1)
+ # r += sr
+ # i += l + 3
+ # continue
+ # # conjonction, like in "|| ( ( foo bar ) baz )" => recurse
+ # if tok == "(":
+ # sr,l = self._parse_deps(deps[i+1:],curuse,level=level+1)
+ # r += sr
+ # i += l + 2
+ # continue
+ # # pkg block "!foo/bar" => ignore it
+ # if tok[0] == "!":
+ # #i += 1
+ # #continue
+ # blocked = True # added
+ # tok = tok[1:] # added
+ # # pick out comparator, if any
+ # cmp = ""
+ # for c in comparators:
+ # if tok.find(c) == 0:
+ # cmp = c
+ # if blocked: cmp = "!"+cmp # added
+ # tok = tok[len(cmp):]
+ # r.append((cmp,curuse,tok))
+ # i += 1
+ # return r,i