Add first draft of PackageSet backend modules
authorMarius Mauch <genone@gentoo.org>
Fri, 6 Jul 2007 00:24:40 +0000 (00:24 -0000)
committerMarius Mauch <genone@gentoo.org>
Fri, 6 Jul 2007 00:24:40 +0000 (00:24 -0000)
svn path=/main/trunk/; revision=7170

pym/portage/sets/__init__.py [new file with mode: 0644]
pym/portage/sets/dbapi.py [new file with mode: 0644]
pym/portage/sets/files.py [new file with mode: 0644]
pym/portage/sets/profiles.py [new file with mode: 0644]
pym/portage/sets/security.py [new file with mode: 0644]
pym/portage/sets/shell.py [new file with mode: 0644]

diff --git a/pym/portage/sets/__init__.py b/pym/portage/sets/__init__.py
new file mode 100644 (file)
index 0000000..2ae1f6b
--- /dev/null
@@ -0,0 +1,120 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+import os
+
+from portage.const import PRIVATE_PATH, USER_CONFIG_PATH
+from portage.exception import InvalidAtom
+from portage.dep import isvalidatom
+
+OPERATIONS = ["merge", "unmerge", "edit"]
+DEFAULT_SETS = ["world", "system", "everything", "security"] \
+       +["package_"+x for x in ["mask", "unmask", "use", "keywords"]]
+
+class PackageSet(object):
+       _operations = ["merge"]
+
+       def __init__(self, name):
+               self._name = name
+               self._nodes = []
+               self._loaded = False
+       
+       def supportsOperation(self, op):
+               if not op in OPERATIONS:
+                       raise ValueError(op)
+               return op in self._operations
+       
+       def getNodes(self):
+               if not self._loaded:
+                       self.load()
+                       self._loaded = True
+               return self._nodes
+
+       def _setNodes(self, nodes):
+               nodes = map(str.strip, nodes)
+               for n in nodes[:]:
+                       if n == "":
+                               nodes.remove(n)
+                       elif not isvalidatom(n):
+                               raise InvalidAtom(n)
+               self._nodes = nodes
+       
+       def getName(self):
+               return self._name
+       
+       def addNode(self, node):
+               if self.supportsOperation("edit"):
+                       self.load()
+                       self._nodes.append(node)
+                       self.write()
+               else:
+                       raise NotImplementedError()
+
+       def removeNode(self, node):
+               if self.supportsOperation("edit"):
+                       self.load()
+                       self._nodes.remove(node)
+                       self.write()
+               else:
+                       raise NotImplementedError()
+
+       def write(self):
+               raise NotImplementedError()
+
+       def load(self):
+               raise NotImplementedError()
+
+class EmptyPackageSet(PackageSet):
+       _operations = ["merge", "unmerge"]
+
+def make_default_sets(configroot, root, profile_paths, settings=None, 
+               vdbapi=None, portdbapi=None):
+       from portage.sets.files import StaticFileSet, ConfigFileSet
+       from portage.sets.profiles import PackagesSystemSet
+       from portage.sets.security import AffectedSet
+       from portage.sets.dbapi import EverythingSet
+       
+       rValue = set()
+       rValue.add(StaticFileSet("world", os.path.join(root, PRIVATE_PATH, "world")))
+       for suffix in ["mask", "unmask", "keywords", "use"]:
+               myname = "package_"+suffix
+               myset = ConfigFileSet(myname, os.path.join(configroot, USER_CONFIG_PATH.lstrip(os.sep), "package."+suffix))
+               rValue.add(myset)
+       rValue.add(PackagesSystemSet("system", profile_paths))
+       if settings != None and portdbapi != None:
+               rValue.add(AffectedSet("security", settings, vdbapi, portdbapi))
+       else:
+               rValue.add(EmptyPackageSet("security"))
+       if vdbapi != None:
+               rValue.add(EverythingSet("everything", vdbapi))
+       else:
+               rValue.add(EmptyPackageSet("everything"))
+
+       return rValue
+
+def make_extra_static_sets(configroot):
+       from portage.sets.files import StaticFileSet
+       
+       rValue = set()
+       mydir = os.path.join(configroot, USER_CONFIG_PATH.lstrip(os.sep), "sets")
+       try:
+               mysets = os.listdir(mydir)
+       except (OSError, IOError):
+               return rValue
+       for myname in mysets:
+               if myname in DEFAULT_SETS:
+                       continue
+               rValue.add(StaticFileSet(fname, os.path.join(mydir, myname)))
+       return rValue
+
+# adhoc test code
+if __name__ == "__main__":
+       import portage
+       l = make_default_sets("/", "/", portage.settings.profiles, portage.settings, portage.db["/"]["vartree"].dbapi, portage.db["/"]["porttree"].dbapi)
+       l.update(make_extra_static_sets("/"))
+       for x in l:
+               print x.getName()+":"
+               for n in sorted(x.getNodes()):
+                       print "- "+n
+               print
diff --git a/pym/portage/sets/dbapi.py b/pym/portage/sets/dbapi.py
new file mode 100644 (file)
index 0000000..65a52c4
--- /dev/null
@@ -0,0 +1,43 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+from portage.versions import catsplit
+
+from portage.sets import PackageSet
+
+class EverythingSet(PackageSet):
+       _operations = ["merge", "unmerge"]
+
+       def __init__(self, name, vdbapi):
+               super(EverythingSet, self).__init__(name)
+               self._db = vdbapi
+       
+       def load(self):
+               mynodes = []
+               for cp in self._db.cp_all():
+                       if len(self._db.cp_list(cp)) > 1:
+                               for cpv in self._db.cp_list(cp):
+                                       myslot = self._db.aux_get(cpv, ["SLOT"])[0]
+                                       mynodes.append(cp+":"+myslot)
+                       else:
+                               mynodes.append(cp)
+               self._setNodes(mynodes)
+
+class CategorySet(PackageSet):
+       _operations = ["merge", "unmerge"]
+       
+       def __init__(self, name, category, portdbapi, only_visible=True):
+               super(CategorySet, self).__init__(name)
+               self._db = portdbapi
+               self._category = category
+               self._check = only_visible
+                       
+       def load(self):
+               mynodes = []
+               for cp in self._db.cp_all():
+                       if catsplit(cp)[0] == self._category:
+                               if (not self._check) or len(self._db.match(cp)) > 0:
+                                       mynodes.append(cp)
+               self._setNodes(mynodes)
+       
diff --git a/pym/portage/sets/files.py b/pym/portage/sets/files.py
new file mode 100644 (file)
index 0000000..a6ddb46
--- /dev/null
@@ -0,0 +1,30 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+from portage.util import grabfile_package, grabdict_package, write_atomic
+
+from portage.sets import PackageSet
+
+class StaticFileSet(PackageSet):
+       _operations = ["merge", "unmerge", "edit"]
+       
+       def __init__(self, name, filename):
+               super(StaticFileSet, self).__init__(name)
+               self._filename = filename
+       
+       def write(self):
+               write_atomic(self._filename, "\n".join(self._nodes)+"\n")
+       
+       def load(self):
+               self._setNodes(grabfile_package(self._filename, recursive=True))
+       
+class ConfigFileSet(StaticFileSet):
+       _operations = ["merge", "unmerge"]
+
+       def write(self):
+               raise NotImplementedError()
+       
+       def load(self):
+               self._setNodes(grabdict_package(self._filename, recursive=True).keys())
+
diff --git a/pym/portage/sets/profiles.py b/pym/portage/sets/profiles.py
new file mode 100644 (file)
index 0000000..37c835a
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+import os
+from portage.util import grabfile_package, stack_lists
+
+from portage.sets import PackageSet
+
+class PackagesSystemSet(PackageSet):
+       _operations = ["merge"]
+
+       def __init__(self, name, profile_paths):
+               super(PackagesSystemSet, self).__init__(name)
+               self._profile_paths = profile_paths
+       
+       def load(self):
+               mylist = [grabfile_package(os.path.join(x, "packages")) for x in self._profile_paths]
+               mylist = stack_lists(mylist, incremental=1)
+               self._setNodes([x[1:] for x in mylist if x[0] == "*"])
diff --git a/pym/portage/sets/security.py b/pym/portage/sets/security.py
new file mode 100644 (file)
index 0000000..2640d29
--- /dev/null
@@ -0,0 +1,43 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+import portage.glsa as glsa
+
+from portage.sets import PackageSet
+
+class SecuritySet(PackageSet):
+       _operations = ["merge"]
+
+       def __init__(self, name, settings, vardbapi, portdbapi):
+               super(SecuritySet, self).__init__(name)
+               self._settings = settings
+               self._vardbapi = vardbapi
+               self._portdbapi = portdbapi
+               
+       def loadCheckfile(self):
+               self._appliedlist = grabfile(os.path.join(os.sep, self._settings["ROOT"], CACHE_PATH, "glsa"))
+       
+       def load(self):
+               glsaindexlist = glsa.get_glsa_list(self._settings)
+               nodelist = []
+               for glsaid in glsaindexlist:
+                       myglsa = glsa.Glsa(glsaid, self._settings, self._vardbapi, self._portdbapi)
+                       #print glsaid, myglsa.isVulnerable(), myglsa.isApplied(), myglsa.getMergeList()
+                       if self.useGlsa(myglsa):
+                               nodelist += myglsa.getMergeList(least_change=False)
+               self._setNodes(nodelist)
+       
+       def useGlsaId(self, glsaid):
+               return True
+       
+       def useGlsa(self, myglsa):
+               return True
+       
+class NewGlsaSet(SecuritySet):
+       def useGlsa(self, myglsa):
+               return not myglsa.isApplied()
+
+class AffectedSet(SecuritySet):
+       def useGlsa(self, myglsa):
+               return myglsa.isVulnerable()
diff --git a/pym/portage/sets/shell.py b/pym/portage/sets/shell.py
new file mode 100644 (file)
index 0000000..ec34eed
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+import subprocess, os
+
+from portage.sets import PackageSet
+
+class CommandOutputSet(PackageSet):
+       _operations = ["merge", "unmerge"]
+
+       def __init__(self, name, command):
+               super(CommandOutputSet, self).__init__(name)
+               self._command = command
+       
+       def load(self):
+               pipe = subprocess.Popen(self._command, stdout=subprocess.PIPE, shell=True)
+               if pipe.wait() == os.EX_OK:
+                       text = pipe.stdout.read()
+                       self._setNodes(text.split("\n"))
+