From 5d9c0db0f421621973121d95f07fd8c72b1ef7ae Mon Sep 17 00:00:00 2001 From: necoro <> Date: Sun, 24 Sep 2006 15:53:02 +0000 Subject: Genetic/One now takes changed useflags into account when calculating dependencies. Plus some minor changes / bugfixes. --- geneticone/flags.py | 31 ++++++------- geneticone/gui/main.py | 118 +++++++++++++++++++++++++++++++++++-------------- geneticone/package.py | 66 ++++++++++++++++++++------- 3 files changed, 150 insertions(+), 65 deletions(-) diff --git a/geneticone/flags.py b/geneticone/flags.py index a523d0c..65088e4 100644 --- a/geneticone/flags.py +++ b/geneticone/flags.py @@ -15,25 +15,26 @@ import os import os.path from subprocess import Popen, PIPE -from geneticone import * +import geneticone +import portage from portage_util import unique_array ### GENERAL PART ### def grep (p, path): """Grep runs "egrep" on a given path and looks for occurences of a given package.""" - if not isinstance(p, Package): - p = Package(p) # assume it is a cpv or a gentoolkit.Package + if not isinstance(p, geneticone.Package): + p = geneticone.Package(p) # assume it is a cpv or a gentoolkit.Package command = "egrep -x -n -r -H '^[<>!=~]{0,2}%s(-[0-9].*)?[[:space:]].*$' %s" return Popen((command % (p.get_cp(), path)), shell = True, stdout = PIPE).communicate()[0].splitlines() -def get_data(pkg): +def get_data(pkg, path): """This splits up the data of grep() and builds tuples in the format (file,line,criterion,list_of_flags).""" flags = [] # do grep - list = grep(pkg, USE_PATH) + list = grep(pkg, path) for i in range(len(list)): file, line, fl = tuple(list[i].split(":")) # get file, line and flag-list @@ -55,7 +56,7 @@ USE_PATH_IS_DIR = os.path.isdir(USE_PATH) 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_flag (_flag): +def invert_use_flag (_flag): if _flag[0] == "-": return _flag[1:] else: @@ -65,16 +66,16 @@ def set_use_flag (pkg, flag): """Sets the useflag for a given package.""" global useFlags, newUseFlags - if not isinstance(pkg, Package): - pkg = Package(pkg) # assume cpv or gentoolkit.Package + if not isinstance(pkg, geneticone.Package): + pkg = geneticone.Package(pkg) # assume cpv or gentoolkit.Package cpv = pkg.get_cpv() - invFlag = invert_flag(flag) + 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) + data = get_data(pkg, USE_PATH) useFlags[cpv] = data else: data = useFlags[cpv] @@ -124,8 +125,8 @@ def set_use_flag (pkg, flag): newUseFlags[cpv] = unique_array(newUseFlags[cpv]) print "newUseFlags: "+str(newUseFlags) -def remove_new_flags (cpv): - if isinstance(cpv, Package): +def remove_new_use_flags (cpv): + if isinstance(cpv, geneticone.Package): cpv = cpv.get_cpv() try: @@ -133,15 +134,15 @@ def remove_new_flags (cpv): except KeyError: pass -def get_new_flags (cpv): - if isinstance(cpv, Package): +def get_new_use_flags (cpv): + if isinstance(cpv, geneticone.Package): cpv = cpv.get_cpv() list2return = [] try: for file, line, flag, remove in newUseFlags[cpv]: if remove: - list2return.append(invert_flag(flag)) + list2return.append(invert_use_flag(flag)) else: list2return.append(flag) except KeyError: diff --git a/geneticone/gui/main.py b/geneticone/gui/main.py index a3d3ae6..e0dceef 100644 --- a/geneticone/gui/main.py +++ b/geneticone/gui/main.py @@ -36,11 +36,22 @@ from portage_util import unique_array class EmergeQueue: """This class manages the emerge queue.""" + def __init__ (self, tree = None, console = None, packages = None): - """"tree" is a gtk.TreeStore to show the queue in; "console" is a vte.Terminal to print the output to.""" - self.mergequeue = {} + """Constructor. + + @param tree: Tree to append all the items to. + @type tree: gtk.TreeStore + @param console: Output is shown here. + @type console: vte.Terminal + @param packages: The list of packages sorted by categories. We will delete the appropriate category if we updated sth. + @type packages: dictionary: {category: list_of_packages}.""" + + self.mergequeue = [] self.unmergequeue = [] + self.iters = {} + self.deps = {} self.tree = tree self.console = console self.packages = packages @@ -51,24 +62,55 @@ class EmergeQueue: else: self.emergeIt = self.unmergeIt = None - def append (self, sth, unmerge = False): + def update_tree (self, it, cpv): + try: + deps = self.deps[cpv] + except KeyError: + deps = geneticone.find_packages("="+cpv)[0].get_dep_packages() + self.deps.update({cpv : deps}) + + subIt = self.tree.append(it, [cpv]) + + for d in deps: + try: + self.update_tree(subIt, d) + except geneticone.BlockedException, e: + while self.tree.iter_parent(subIt): + subIt = self.tree.iter_parent(subIt) + self.remove_children(subIt) + raise e + + self.iters.update({cpv: subIt}) + + def append (self, sth, unmerge = False, update = False): """Appends a cpv either to the merge queue or to the unmerge-queue. Also update the tree-view.""" if not unmerge: - # insert dependencies - pkg = geneticone.find_packages("="+sth)[0] try: - self.mergequeue.update({sth : pkg.get_dep_packages()}) + # insert dependencies + pkg = geneticone.find_packages("="+sth)[0] + deps = pkg.get_dep_packages() + + if update: + if deps == self.deps[sth]: + 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) + except geneticone.BlockedException, e : blocks = e[0] blocked_dialog(sth, blocks) return - else: - # update tree - if self.emergeIt: - pkgIt = self.tree.append(self.emergeIt, [sth]) - for p in self.mergequeue[sth]: - self.tree.append(pkgIt, [p]) else: self.unmergequeue.append(sth) if self.unmergeIt: # update tree @@ -82,7 +124,7 @@ class EmergeQueue: cat = geneticone.split_package_name(p)[0] while cat[0] in ["=",">","<","!"]: cat = cat[1:] - print cat + print cat, del self.packages[cat] print "deleted" except KeyError: @@ -94,19 +136,19 @@ class EmergeQueue: self.console.set_pty(master) 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() - self.remove_all(it) + 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 list = [] - for k in self.mergequeue.keys(): + for k in self.mergequeue: list += ["="+k] s = [] if not force: s = ["-pv"] - self._emerge(s,list, self.emergeIt) + 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.""" @@ -117,7 +159,7 @@ class EmergeQueue: if not force: s = ["-Cpv"] self._emerge(s,list, self.unmergeIt) - def remove_all (self, parentIt): + def remove_children (self, parentIt): """Removes all children of a given parent TreeIter.""" childIt = self.tree.iter_children(parentIt) @@ -125,14 +167,19 @@ class EmergeQueue: temp = childIt childIt = self.tree.iter_next(childIt) self.remove(temp) - + def remove (self, it): """Removes a specific item in the tree.""" 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): - del self.mergequeue[cpv] - flags.remove_new_flags(cpv) + try: + self.mergequeue.remove(cpv) + del self.iters[cpv] + del self.deps[cpv] + except ValueError: + pass + flags.remove_new_use_flags(cpv) else: self.unmergequeue.remove(cpv) @@ -141,14 +188,16 @@ class EmergeQueue: class PackageWindow: """A window with data about a specfic package.""" - def __init__ (self, parent, cp, queue = None, version = None, delOnClose = True): + def __init__ (self, parent, cp, queue = None, version = None, delOnClose = True, doEmerge = True): """Build up window contents.""" self.parent = parent # parent window self.cp = cp # category/package self.version = version # version - if not None this is used self.queue = queue self.delOnClose = delOnClose - + self.doEmerge = doEmerge + self.flagChanged = False + # window self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_title(cp) @@ -219,7 +268,7 @@ class PackageWindow: self.emergeBtn = gtk.Button("_Emerge") self.unmergeBtn = gtk.Button("_Unmerge") - if not self.queue: + if not self.queue or not doEmerge: self.emergeBtn.set_sensitive(False) self.unmergeBtn.set_sensitive(False) self.cancelBtn = gtk.Button("_Cancel") @@ -296,14 +345,15 @@ class PackageWindow: def cb_button_pressed (self, b, event, data = None): """Callback for pressed checkboxes. Just quits the event-loop - no redrawing.""" - print b if not isinstance(b, gtk.CellRendererToggle): b.emit_stop_by_name("button-press-event") - print "hallo" return True def cb_cancel_clicked (self, button, data = None): - if self.delOnClose: flags.remove_new_flags(self.actual_package()) + if self.delOnClose: self.actual_package().remove_new_use_flags() + if self.flagChanged: + if self.queue: + self.queue.append(self.actual_package().get_cpv(), update = True) self.window.destroy() return True @@ -334,7 +384,8 @@ class PackageWindow: prefix = "" if not store[path][0]: prefix = "-" - flags.set_use_flag(self.actual_package(), prefix+store[path][1]) + self.actual_package().set_use_flag(prefix+store[path][1]) + self.flagChanged = True return True def update_checkboxes (self): @@ -348,13 +399,12 @@ class PackageWindow: store = gtk.ListStore(bool, str, str) pkg = self.actual_package() - newUses = flags.get_new_flags(pkg) - for use in pkg.get_all_useflags(): - if pkg.is_installed() and use in pkg.get_set_useflags() and not flags.invert_flag(use) in newUses: # flags set during install + for use in pkg.get_all_use_flags(): + if pkg.is_installed() and use in pkg.get_actual_use_flags(): # flags set during install enabled = True - elif (not pkg.is_installed()) and use in pkg.get_settings("USE").split() and not flags.invert_flag(use) in newUses: # flags that would be set + elif (not pkg.is_installed()) and use in pkg.get_settings("USE").split() and not flags.invert_use_flag(use) in pkg.get_new_use_flags(): # flags that would be set enabled = True - elif use in newUses: + elif use in pkg.get_new_use_flags(): enabled = True else: enabled = False @@ -574,7 +624,7 @@ class MainWindow: package = store.get_value(store.get_iter(path), 0) cat, name, vers, rev = geneticone.split_package_name(package) if rev != "r0": vers = vers+"-"+rev - PackageWindow(self.window, cat+"/"+name, queue = None, version = vers, delOnClose=False) + PackageWindow(self.window, cat+"/"+name, queue = self.queue, version = vers, delOnClose = False, doEmerge = False) return True def create_cat_list (self): @@ -638,7 +688,7 @@ class MainWindow: if model.iter_n_children(iter) > 0: # and has children which can be removed :) askMB = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "Do you really want to clear the whole queue?") if askMB.run() == gtk.RESPONSE_YES : - self.queue.remove_all(iter) + self.queue.remove_children(iter) askMB.destroy() elif model.iter_parent(model.iter_parent(iter)): # this is in the 3rd level => dependency infoMB = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "You cannot remove dependencies. :)") diff --git a/geneticone/package.py b/geneticone/package.py index 6916f49..9df92c7 100644 --- a/geneticone/package.py +++ b/geneticone/package.py @@ -12,6 +12,8 @@ # Written by Necoro d.M. from geneticone import * +from geneticone import flags +import geneticone import gentoolkit import portage @@ -48,10 +50,44 @@ class Package (gentoolkit.Package): def get_size (self): return self.size() - def get_all_useflags (self): + def get_all_use_flags (self): """Returns a list of _all_ useflags for this package.""" 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.""" + if self.is_installed(): + uses = self.get_use_flags().split() + iuses = self.get_all_use_flags() + set = [] + for u in iuses: + if u in uses: + set.append(u) + return set + else: + return [] + + def get_new_use_flags (self): + return flags.get_new_use_flags(self) + + def get_actual_use_flags (self): + if self.is_installed(): + i_flags = self.get_installed_use_flags() + for f in self.get_new_use_flags(): + if flags.invert_flag(f) in i_flags: + i_flags.remove(flags.invert_flag(f)) + elif f not in i_flags: + i_flags.append(f) + return i_flags + else: + return self.get_new_flags() + + def set_use_flag (self, flag): + flags.set_use_flag(self, flag) + + def remove_new_use_flags (self): + 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), ...]""" @@ -62,9 +98,20 @@ class Package (gentoolkit.Package): raises: BlockedException, PackageNotFoundException.""" dep_pkgs = [] # the package list + # check whether we got use-flags which are not visible for portage yet + newUseFlags = self.get_new_use_flags() + actual = self.get_settings("USE").split() + if newUseFlags: + depUses = [] + for u in newUseFlags: + if u[0] == "-" and flags.invert_use_flag(u) in actual: + actual.remove(flags.invert_use_flag(u)) + elif u not in actual: + actual.append(u) + # let portage do the main stuff ;) # pay attention to any changes here - deps = portage.dep_check (self.get_env_var("RDEPEND")+" "+self.get_env_var("DEPEND"), vartree.dbapi, self._settings) + deps = portage.dep_check (self.get_env_var("RDEPEND")+" "+self.get_env_var("DEPEND")+" "+self.get_env_var("PDEPEND"), vartree.dbapi, self._settings, myuse = actual) if not deps: # what is the difference to [1, []] ? return [] @@ -103,7 +150,7 @@ class Package (gentoolkit.Package): # get useflags if self.is_installed(): - uses = self.get_set_useflags() + uses = self.get_installed_use_flags() else: uses = self.get_settings("USE") @@ -142,19 +189,6 @@ class Package (gentoolkit.Package): return unique_array(dep_packages) - def get_set_useflags (self): - """Returns a list of the useflags enabled at installation time. If package is not installed, it returns an empty list.""" - if self.is_installed(): - uses = self.get_use_flags().split() - iuses = self.get_all_useflags() - set = [] - for u in iuses: - if u in uses: - set.append(u) - return set - else: - return [] - def get_cp (self): """Returns category/package.""" return self.get_category()+"/"+self.get_name() -- cgit v1.2.3-70-g09d2