=== pym/portage_sets.py ================================================================== --- pym/portage_sets.py (/fruitage/portage) (revision 1521) +++ pym/portage_sets.py (/local/fruitage) (revision 1521) @@ -0,0 +1,89 @@ +# portage_sets.py - Portage Sets functionality +# Copyright 2006 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id: $ + +import os + +from portage_dep import isvalidatom +from portage_const import SET_PATH, WORLD_FILE + +class PackageSet(list): + """ Abstract PackageSet Class + Ironically this is a python list and NOT a set, as we need to preserve + order here. + """ + + def __init__( self ): + """ All PackageSet classes have items """ + self.items = None + +def PackageSetFactory( set_name, root="/", settings=None ): + """ Give me a valid set_name and I'll make you the right one. + (settings,root) are require for certain types of Sets (glsa,all,system) """ + + if os.path.exists( SET_PATH + os.sep + set_name ): + return PackageSetFile( SET_PATH + os.sep + set_name ) + elif set_name in "world": + return WorldSet( root ) + elif not settings: + raise ValueError( "Settings is require for sets: %s" % ["system","all","glsa"] ) + elif set_name in "system": + return SystemSet( settings ) + elif set_name in "all": + return AllSet( root, settings ) + elif set_name in "glsa": + return GLSASet( settings ) + else: + return PackageSetFile( set_name ) + +class AllSet(PackageSet): + """ Returns a set of all installed packages (CPs) """ + + def __init__( self, root, settings ): + """ Pass me a config to work with. """ + from portage import vartree + vartree = vartree( root=root, settings=settings ) + self.items = vartree.dbapi.cp_all() + +class SystemSet(PackageSet): + """ Returns a set of all packages in 'system' """ + + def __init__( self, settings ): + """ I need a config object to inspect. """ + # settings.packages all start with "*", so we strip it here. + self.items = [item[1:] for item in settings.packages + if item.startswith("*")] + +class PackageSetList(PackageSet): + """ Represents a set of packages """ + + def __init__( self, cpvs ): + """ Create a new object given a list of atoms (cps or cpvs) """ + self.items = cpvs + +class WorldSet(PackageSet): + """ Represents everything in "world", aka installed manually by the user. """ + + def __init__( self, root ): + """ Create a new object given a root to pull from. """ + self.items = PackageSetFile( root + WORLD_FILE ).items + +class GLSASet(PackageSet): + """ Represents a set of packages worth upgrading for security reasons """ + + def __init__( self, root ): + raise NotImplementedError("GLSA Set is not written yet") + +class PackageSetFile(PackageSet): + """ Represents a set of packages loaded from a file""" + + def __init__( self, filename ): + """ Create a new object given a filename to load a set from """ + handle = open(filename, "r") + items = handle.readlines() + items = [l for l in items if not l.startswith("#")] + items = [item.rstrip() for item in items] + items = [pkg for pkg in items if isvalidatom(pkg)] + self.items = items + self.filename = filename === pym/portage_const.py ================================================================== --- pym/portage_const.py (/fruitage/portage) (revision 1521) +++ pym/portage_const.py (/local/fruitage) (revision 1521) @@ -14,6 +14,7 @@ DEPCACHE_PATH = CACHE_PATH+"/dep" USER_CONFIG_PATH = "/etc/portage" +SET_PATH = USER_CONFIG_PATH+"/sets" MODULES_FILE_PATH = USER_CONFIG_PATH+"/modules" CUSTOM_PROFILE_PATH = USER_CONFIG_PATH+"/profile" === bin/emerge ================================================================== --- bin/emerge (/fruitage/portage) (revision 1521) +++ bin/emerge (/local/fruitage) (revision 1521) @@ -40,6 +40,8 @@ import portage_locks import portage_exception from portage_data import secpass +from portage_const import SET_PATH +from portage_sets import PackageSetFactory if not hasattr(__builtins__, "set"): from sets import Set as set @@ -178,7 +180,7 @@ "clean", "config", "depclean", "info", "metadata", "prune", "regen", "search", -"sync", "system", "unmerge", "world", +"sync", "unmerge", ] options=[ "--ask", "--alphabetical", @@ -348,15 +350,17 @@ #configure emerge engine parameters # # self: include _this_ package regardless of if it is merged. - # selective: exclude the package if it is merged + # selective: exclude the package if it is merged. # recurse: go into the dependencies # deep: go into the dependencies of already merged packages # empty: pretend nothing is merged myparams=["self","recurse"] add=[] sub=[] - if "--update" in myopts or myaction in ("system", "world"): + if "--update" in myopts: add.extend(["selective","empty"]) + if "--package-set" in myopts: + add.extend(["selective"]) if "--emptytree" in myopts: add.extend(["empty"]) sub.extend(["selective"]) @@ -368,8 +372,6 @@ add.extend(["deep"]) if "--selective" in myopts: add.extend(["selective"]) - if myaction in ["world","system"]: - add.extend(["selective"]) elif myaction in ["depclean"]: add.extend(["empty"]) sub.extend(["selective"]) @@ -1226,56 +1228,101 @@ retlist.append(y) return retlist - def xcreate(self,mode="system"): - world_problems = False - if mode=="system": - mylist = getlist(self.settings, "system") - else: - #world mode - worldlist = getlist(self.settings, "world") - sysdict = genericdict(getlist(self.settings, "system")) - worlddict=genericdict(worldlist) + def setCreate( self, set_name ): + """ + Checks dependencies on all sets (system + world) + Replaces xcreate() - for x in worlddict.keys(): - if not portage.isvalidatom(x): - world_problems = True - elif not self.trees[self.target_root]["vartree"].dbapi.match(x): - world_problems = True - else: - sysdict[x]=worlddict[x] + @param set_name: Name of item to merge. + @type set_name: String + @rtype: bool + @returns: True if set exists and has proper deps, false if improper deps + and raises ParseError if set_name is not a set. - mylist = sysdict.keys() + """ - newlist = [] - for atom in mylist: - if portage.dep_getkey(atom).split("/")[-1] == "portage": - newlist.insert(0, atom) - else: - newlist.append(atom) - mylist = newlist - + try: + _set = PackageSetFactory( set_name, self.target_root, self.settings ) + except IOError: + error = portage_exception.ParseError("%s is not a set" % set_name) + error.pkg = set_name + raise error + missing_atoms = [] - for mydep in mylist: + for pkg in _set.items: try: if not self.select_dep( - self.target_root, mydep, raise_on_missing=True): - print "\n\n!!! Problem resolving dependencies for", mydep + self.target_root, pkg, raise_on_missing=True): + portage.writemsg_stdout( "\n!!! Problem resolving dependencies for %s" % mydep ) return 0 except ValueError: - missing_atoms.append(mydep) - - if world_problems: - print "\n!!! Problems have been detected with your world file" - print "!!! Please run "+green("emaint --check world")+"\n" - + """ Atom is missing from PORTTREE; so we quickly + check for it in the VDB; if it's there we don't bitch + """ + if not self.trees[self.target_root]["vartree"].dbapi.match(pkg): + missing_atoms.append( pkg ) if missing_atoms: - print "\n" + colorize("BAD", "!!!") + \ - " Ebuilds for the following packages are either all" - print colorize("BAD", "!!!") + " masked or don't exist:" - print " ".join(missing_atoms) + "\n" + portage.writemsg_stdout( "\n" + colorize("BAD", "!!!") + \ + " Ebuilds for the following packages are either all\n") + portage.writemsg_stdout( colorize("BAD", "!!!") + " masked or don't exist:") + portage.writemsg_stdout( colorize("BAD", "\n!!!").join( missing_atoms) + "\n") return 1 + def xcreate(self,mode="system"): + + if False: + world_problems = False + if mode=="system": + mylist = getlist(self.settings, "system") + else: + #world mode + worldlist = getlist(self.settings, "world") + sysdict = genericdict(getlist(self.settings, "system")) + worlddict=genericdict(worldlist) + + for x in worlddict.keys(): + if not portage.isvalidatom(x): + world_problems = True + elif not self.trees[self.target_root]["vartree"].dbapi.match(x): + world_problems = True + else: + sysdict[x]=worlddict[x] + + mylist = sysdict.keys() + + newlist = [] + for atom in mylist: + if portage.dep_getkey(atom).split("/")[-1] == "portage": + newlist.insert(0, atom) + else: + newlist.append(atom) + mylist = newlist + + missing_atoms = [] + for mydep in mylist: + try: + if not self.select_dep( + self.target_root, mydep, raise_on_missing=True): + print "\n\n!!! Problem resolving dependencies for", mydep + return 0 + except ValueError: + missing_atoms.append(mydep) + + if world_problems: + print "\n!!! Problems have been detected with your world file" + print "!!! Please run "+green("emaint --check world")+"\n" + + if missing_atoms: + print "\n" + colorize("BAD", "!!!") + \ + " Ebuilds for the following packages are either all" + print colorize("BAD", "!!!") + " masked or don't exist:" + print " ".join(missing_atoms) + "\n" + + return 1 + else: + raise NotImplementedError("Xcreate is depreated") + def match(self, mydep, myroot=None, mykey=None): # support mutual exclusive deps if myroot is None: @@ -2208,6 +2255,8 @@ mysettings = portage.config(clone=settings) + ### XXX Fix unmerge logic to work with sets ? + if not unmerge_files or "world" in unmerge_files or "system" in unmerge_files: if "unmerge"==unmerge_action: print @@ -3047,6 +3096,8 @@ print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)} print "done!" +### XXX Fix config to not take sets + def action_config(settings, trees, myopts, myfiles): if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles: print red("!!! config can only take a single package atom at this time\n") @@ -3308,9 +3359,9 @@ myvarlist = vardb.cpv_all() if not syslist: - print "\n!!! You have no system list.", + print "\n!!! You have no system set.", if not worldlist: - print "\n!!! You have no world file.", + print "\n!!! You have no world set.", if not myvarlist: print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH, @@ -3447,39 +3498,46 @@ print darkgreen("emerge: It seems we have nothing to resume...") sys.exit(0) + + """ Here we parse the command line args, we try sets first, then + normal packages. + """ + myparams = create_depgraph_params(myopts, myaction) mydepgraph = depgraph(settings, trees, myopts, myparams, spinner) - if myaction in ["system","world"]: - if not ("--quiet" in myopts): - print "Calculating",myaction,"dependencies ", - sys.stdout.flush() - if not mydepgraph.xcreate(myaction): - print "!!! Depgraph creation failed." - sys.exit(1) - if not ("--quiet" in myopts): - print "\b\b... done!" - else: - if not ("--quiet" in myopts): - print "Calculating dependencies ", - sys.stdout.flush() + + mypackages = [] + unfulfilled_sets = [] + sets = myfiles + portage.writemsg_stdout( "\nCalculating dependencies: " ) + + for p_set in sets: try: - retval, favorites = mydepgraph.select_files(myfiles) + if not mydepgraph.setCreate(p_set): + unfulfilled_sets.append(p_set) + except portage_exception.ParseError, pe: + mypackages.append( pe.pkg ) + if unfulfilled_sets: + raise Exception( "Depgraph creation failed for: %s" % unfulfilled_sets ) + elif mypackages: + try: + retval, favorites = mydepgraph.select_files(mypackages) except portage_exception.PackageNotFound, e: portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1) sys.exit(1) if not retval: sys.exit(1) if not ("--quiet" in myopts): - print "\b\b... done!" + portage.writemsg( "\b\b... done!" ) if ("--usepkgonly" in myopts) and mydepgraph.missingbins: - sys.stderr.write(red("The following binaries are not available for merging...\n")) + portage.writemsg_stderr(red("The following binaries are not available for merging...\n")) if mydepgraph.missingbins: for x in mydepgraph.missingbins: - sys.stderr.write(" "+str(x)+"\n") - sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n") + portage.writemsg_stderr(" "+str(x)+"\n") + portage.writemsg_stderr("\nThese are required by '--usepkgonly' -- Terminating.\n\n") sys.exit(1) if "--ask" in myopts: @@ -3631,8 +3689,7 @@ myopts.append(x) elif x[2:] in actions: if myaction: - if myaction not in ["system", "world"]: - myaction="--"+myaction + myaction="--"+myaction print print red("!!!")+green(" Multiple actions requested... Please choose one only.") print red("!!!")+" '"+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'" @@ -3643,8 +3700,7 @@ print "!!! Error:",x,"is an invalid option." sys.exit(1) elif (not myaction) and (x in actions): - if x not in ["system", "world"]: - print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x)) + print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x)) if myaction: print print red("!!!")+green(" Multiple actions requested... Please choose one only.") @@ -3833,10 +3889,6 @@ """ - if (myaction in ["world", "system"]) and myfiles: - print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both." - sys.exit(1) - for x in myfiles: ext = os.path.splitext(x)[1] if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)): Property changes on: ___________________________________________________________________ Name: svk:merge +ac592a22-f3fe-0310-977e-98394eae9e84:/main/trunk:4434