commit:     3e327e8c849cf6bfb84a3a3ec5c080ab4bc4653c
Author:     Michał Górny <mgorny <AT> gentoo <DOT> org>
AuthorDate: Sun Nov 30 23:00:20 2014 +0000
Commit:     Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Sun Dec  7 22:57:08 2014 +0000
URL:        
http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=3e327e8c

Split @selected into @selected-packages and @selected-sets

Split the big @selected set into separate @selected-packages for plain
packages and @selected-sets for subsets. The @selected set is still
provided as compatibility wrapper for both, though the new sets are
preferred for more flexibility.

---
 bin/regenworld                |   4 +-
 cnf/sets/portage.conf         |   7 +-
 doc/config/sets.docbook       |  18 +++--
 man/emerge.1                  |  16 +++--
 pym/portage/_sets/__init__.py |   8 +++
 pym/portage/_sets/files.py    | 149 ++++++++++++++++++++++++++++--------------
 6 files changed, 137 insertions(+), 65 deletions(-)

diff --git a/bin/regenworld b/bin/regenworld
index e07424d..eef4cfd 100755
--- a/bin/regenworld
+++ b/bin/regenworld
@@ -11,7 +11,7 @@ if 
osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".porta
 import portage
 portage._internal_caller = True
 from portage import os
-from portage._sets.files import StaticFileSet, WorldSelectedSet
+from portage._sets.files import StaticFileSet, WorldSelectedPackagesSet
 
 import re
 import tempfile
@@ -105,7 +105,7 @@ for mykey in biglist:
 if not worldlist:
        pass
 else:
-       existing_set = WorldSelectedSet(eroot)
+       existing_set = WorldSelectedPackagesSet(eroot)
        existing_set.load()
 
        if not existing_set:

diff --git a/cnf/sets/portage.conf b/cnf/sets/portage.conf
index fd2c387..8ffcedc 100644
--- a/cnf/sets/portage.conf
+++ b/cnf/sets/portage.conf
@@ -9,10 +9,15 @@
 class = portage.sets.base.DummyPackageSet
 packages = @selected @system
 
-# Not much that could be changed for world, so better leave it alone
 [selected]
 class = portage.sets.files.WorldSelectedSet
 
+[selected-packages]
+class = portage.sets.files.WorldSelectedPackagesSet
+
+[selected-sets]
+class = portage.sets.files.WorldSelectedSetsSet
+
 # Same as for world, though later portage versions might use a different class
 [system]
 class = portage.sets.profiles.PackagesSystemSet

diff --git a/doc/config/sets.docbook b/doc/config/sets.docbook
index 8f74412..cf8dcf3 100644
--- a/doc/config/sets.docbook
+++ b/doc/config/sets.docbook
@@ -71,9 +71,9 @@
                        class = portage.sets.base.DummyPackageSet
                        packages = @selected @system
 
-                       # The selected set
-                       [selected]
-                       class = portage.sets.files.WorldSelectedSet
+                       # The selected-packages set
+                       [selected-packages]
+                       class = portage.sets.files.WorldSelectedPackagesSet
 
                        # The classic system set
                        [system]
@@ -247,8 +247,16 @@
                        </sect3>
                </sect2>
                
-               <sect2 id='config-set-classes-WorldSelectedSet'>
-               <title>portage.sets.files.WorldSelectedSet</title>
+               <sect2 id='config-set-classes-WorldSelectedPackagesSet'>
+               <title>portage.sets.files.WorldSelectedPackagesSet</title>
+               <para>
+               A minor variation of <classname>StaticFileSet</classname>, 
mainly for implementation 
+               reasons. It should never be used in user configurations as it's 
already configured
+               by default, doesn't support any options and will eventually be 
removed in a future version.
+               </para>
+
+               <sect2 id='config-set-classes-WorldSelectedSetsSet'>
+               <title>portage.sets.files.WorldSelectedSetsSet</title>
                <para>
                A minor variation of <classname>StaticFileSet</classname>, 
mainly for implementation 
                reasons. It should never be used in user configurations as it's 
already configured

diff --git a/man/emerge.1 b/man/emerge.1
index 2f01de8..be46a7d 100644
--- a/man/emerge.1
+++ b/man/emerge.1
@@ -61,13 +61,15 @@ would like to query the owners of one or more files or 
directories.
 .TP
 .BR set
 A \fIset\fR is a convenient shorthand for a large group of
-packages. Three sets are currently always available: \fBselected\fR,
-\fBsystem\fR and \fBworld\fR. \fBselected\fR contains the user-selected
-"world" packages that are listed in \fB/var/lib/portage/world\fR,
-and nested sets that may be listed
-in \fB/var/lib/portage/world_sets\fR. \fBsystem\fR refers to a set of
-packages deemed necessary for your system to run properly. \fBworld\fR
-encompasses both the \fBselected\fR and \fBsystem\fR sets. [See
+packages. Five sets are currently always available: \fBselected-packages\fR,
+\fBselected-sets\fR, \fBselected\fR, \fBsystem\fR and \fBworld\fR.
+\fBselected-packages\fR contains the user-selected "world" packages that
+are listed in \fB/var/lib/portage/world\fR, while \fBselected-sets\fR
+contains the nested sets that may be listed in 
\fB/var/lib/portage/world_sets\fR.
+\fBsystem\fR refers to a set of packages deemed necessary for your system
+to run properly. \fBselected\fR encompasses both the \fBselected-packages\fR
+and \fBselected-sets\fR sets, while \fBworld\fR encompasses the \fBselected\fR
+and \fBsystem\fR sets. [See
 \fBFILES\fR below for more information.] Other sets can exist depending
 on the current configuration. The default set configuration is located
 in the \fB/usr/share/portage/config/sets\fR directory.

diff --git a/pym/portage/_sets/__init__.py b/pym/portage/_sets/__init__.py
index 75d1df7..a652227 100644
--- a/pym/portage/_sets/__init__.py
+++ b/pym/portage/_sets/__init__.py
@@ -121,6 +121,14 @@ class SetConfig(object):
                parser.add_section("selected")
                parser.set("selected", "class", 
"portage.sets.files.WorldSelectedSet")
 
+               parser.remove_section("selected-packages")
+               parser.add_section("selected-packages")
+               parser.set("selected-packages", "class", 
"portage.sets.files.WorldSelectedPackagesSet")
+
+               parser.remove_section("selected-sets")
+               parser.add_section("selected-sets")
+               parser.set("selected-sets", "class", 
"portage.sets.files.WorldSelectedSetsSet")
+
                parser.remove_section("system")
                parser.add_section("system")
                parser.set("system", "class", 
"portage.sets.profiles.PackagesSystemSet")

diff --git a/pym/portage/_sets/files.py b/pym/portage/_sets/files.py
index 2fb64de..e76fa83 100644
--- a/pym/portage/_sets/files.py
+++ b/pym/portage/_sets/files.py
@@ -20,7 +20,8 @@ from portage.env.loaders import ItemFileLoader, 
KeyListFileLoader
 from portage.env.validators import ValidAtomValidator
 from portage import cpv_getkey
 
-__all__ = ["StaticFileSet", "ConfigFileSet", "WorldSelectedSet"]
+__all__ = ["StaticFileSet", "ConfigFileSet", "WorldSelectedSet",
+               "WorldSelectedPackagesSet", "WorldSelectedSetsSet"]
 
 class StaticFileSet(EditablePackageSet):
        _operations = ["merge", "unmerge"]
@@ -205,41 +206,59 @@ class ConfigFileSet(PackageSet):
        multiBuilder = classmethod(multiBuilder)
 
 class WorldSelectedSet(EditablePackageSet):
-       description = "Set of packages that were directly installed by the user"
-       
+       description = "Set of packages and subsets that were directly installed 
by the user"
+
        def __init__(self, eroot):
                super(WorldSelectedSet, self).__init__(allow_repo=True)
-               # most attributes exist twice as atoms and non-atoms are stored 
in 
-               # separate files
+               self._pkgset = WorldSelectedPackagesSet(eroot)
+               self._setset = WorldSelectedSetsSet(eroot)
+
+       def write(self):
+               self._pkgset._atoms = self._atoms
+               self._pkgset.write()
+               self._setset._nonatoms = self._nonatoms
+               self._setset.write()
+
+       def load(self):
+               self._pkgset.load()
+               self._setset.load()
+               self._setAtoms(self._pkgset._atoms | self._pkgset._nonatoms)
+
+       def lock(self):
+               self._pkgset.lock()
+               self._setset.lock()
+
+       def unlock(self):
+               self._pkgset.unlock()
+               self._setset.unlock()
+
+       def cleanPackage(self, vardb, cpv):
+               self._pkgset.cleanPackage(vardb, cpv)
+
+       def singleBuilder(self, options, settings, trees):
+               return WorldSelectedSet(settings["EROOT"])
+       singleBuilder = classmethod(singleBuilder)
+
+class WorldSelectedPackagesSet(EditablePackageSet):
+       description = "Set of packages that were directly installed by the user"
+
+       def __init__(self, eroot):
+               super(WorldSelectedPackagesSet, self).__init__(allow_repo=True)
                self._lock = None
                self._filename = os.path.join(eroot, WORLD_FILE)
                self.loader = ItemFileLoader(self._filename, self._validate)
                self._mtime = None
-               
-               self._filename2 = os.path.join(eroot, WORLD_SETS_FILE)
-               self.loader2 = ItemFileLoader(self._filename2, self._validate2)
-               self._mtime2 = None
-               
+
        def _validate(self, atom):
                return ValidAtomValidator(atom, allow_repo=True)
 
-       def _validate2(self, setname):
-               return setname.startswith(SETPREFIX)
-
        def write(self):
                write_atomic(self._filename,
                        "".join(sorted("%s\n" % x for x in self._atoms)))
 
-               write_atomic(self._filename2,
-                       "".join(sorted("%s\n" % x for x in self._nonatoms)))
-
        def load(self):
                atoms = []
-               nonatoms = []
                atoms_changed = False
-               # load atoms and non-atoms from different files so the 
worldfile is 
-               # backwards-compatible with older versions and other PMs, even 
though 
-               # it's supposed to be private state data :/
                try:
                        mtime = os.stat(self._filename).st_mtime
                except (OSError, IOError):
@@ -261,36 +280,8 @@ class WorldSelectedSet(EditablePackageSet):
                else:
                        atoms.extend(self._atoms)
 
-               changed2, nonatoms = self._load2()
-               atoms_changed |= changed2
-
                if atoms_changed:
-                       self._setAtoms(atoms+nonatoms)
-
-       def _load2(self):
-               changed = False
-               try:
-                       mtime = os.stat(self._filename2).st_mtime
-               except (OSError, IOError):
-                       mtime = None
-               if (not self._loaded or self._mtime2 != mtime):
-                       try:
-                               data, errors = self.loader2.load()
-                               for fname in errors:
-                                       for e in errors[fname]:
-                                               self.errors.append(fname+": "+e)
-                       except EnvironmentError as e:
-                               if e.errno != errno.ENOENT:
-                                       raise
-                               del e
-                               data = {}
-                       nonatoms = list(data)
-                       self._mtime2 = mtime
-                       changed = True
-               else:
-                       nonatoms = list(self._nonatoms)
-
-               return changed, nonatoms
+                       self._setAtoms(atoms)
 
        def _ensure_dirs(self):
                ensure_dirs(os.path.dirname(self._filename), gid=portage_gid, 
mode=0o2750, mask=0o2)
@@ -338,5 +329,63 @@ class WorldSelectedSet(EditablePackageSet):
                self.replace(newworldlist)
 
        def singleBuilder(self, options, settings, trees):
-               return WorldSelectedSet(settings["EROOT"])
+               return WorldSelectedPackagesSet(settings["EROOT"])
+       singleBuilder = classmethod(singleBuilder)
+
+class WorldSelectedSetsSet(EditablePackageSet):
+       description = "Set of sets that were directly installed by the user"
+
+       def __init__(self, eroot):
+               super(WorldSelectedSetsSet, self).__init__(allow_repo=True)
+               self._lock = None
+               self._filename = os.path.join(eroot, WORLD_SETS_FILE)
+               self.loader = ItemFileLoader(self._filename, self._validate)
+               self._mtime = None
+
+       def _validate(self, setname):
+               return setname.startswith(SETPREFIX)
+
+       def write(self):
+               write_atomic(self._filename,
+                       "".join(sorted("%s\n" % x for x in self._nonatoms)))
+
+       def load(self):
+               atoms_changed = False
+               try:
+                       mtime = os.stat(self._filename).st_mtime
+               except (OSError, IOError):
+                       mtime = None
+               if (not self._loaded or self._mtime != mtime):
+                       try:
+                               data, errors = self.loader.load()
+                               for fname in errors:
+                                       for e in errors[fname]:
+                                               self.errors.append(fname+": "+e)
+                       except EnvironmentError as e:
+                               if e.errno != errno.ENOENT:
+                                       raise
+                               del e
+                               data = {}
+                       nonatoms = list(data)
+                       self._mtime = mtime
+                       atoms_changed = True
+               else:
+                       nonatoms = list(self._nonatoms)
+
+               if atoms_changed:
+                       self._setAtoms(nonatoms)
+
+       def lock(self):
+               if self._lock is not None:
+                       raise AssertionError("already locked")
+               self._lock = lockfile(self._filename, wantnewlockfile=1)
+
+       def unlock(self):
+               if self._lock is None:
+                       raise AssertionError("not locked")
+               unlockfile(self._lock)
+               self._lock = None
+
+       def singleBuilder(self, options, settings, trees):
+               return WorldSelectedSetsSet(settings["EROOT"])
        singleBuilder = classmethod(singleBuilder)

Reply via email to