1 |
Split the big @selected set into separate @selected-packages for plain |
2 |
packages and @selected-sets for subsets. The @selected set is still |
3 |
provided as compatibility wrapper for both, though the new sets are |
4 |
preferred for more flexibility. |
5 |
--- |
6 |
bin/regenworld | 4 +- |
7 |
cnf/sets/portage.conf | 7 +- |
8 |
doc/config/sets.docbook | 18 +++-- |
9 |
man/emerge.1 | 16 +++-- |
10 |
pym/portage/_sets/__init__.py | 8 +++ |
11 |
pym/portage/_sets/files.py | 149 ++++++++++++++++++++++++++++-------------- |
12 |
6 files changed, 137 insertions(+), 65 deletions(-) |
13 |
|
14 |
diff --git a/bin/regenworld b/bin/regenworld |
15 |
index e07424d..eef4cfd 100755 |
16 |
--- a/bin/regenworld |
17 |
+++ b/bin/regenworld |
18 |
@@ -11,7 +11,7 @@ if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".porta |
19 |
import portage |
20 |
portage._internal_caller = True |
21 |
from portage import os |
22 |
-from portage._sets.files import StaticFileSet, WorldSelectedSet |
23 |
+from portage._sets.files import StaticFileSet, WorldSelectedPackagesSet |
24 |
|
25 |
import re |
26 |
import tempfile |
27 |
@@ -105,7 +105,7 @@ for mykey in biglist: |
28 |
if not worldlist: |
29 |
pass |
30 |
else: |
31 |
- existing_set = WorldSelectedSet(eroot) |
32 |
+ existing_set = WorldSelectedPackagesSet(eroot) |
33 |
existing_set.load() |
34 |
|
35 |
if not existing_set: |
36 |
diff --git a/cnf/sets/portage.conf b/cnf/sets/portage.conf |
37 |
index fd2c387..8ffcedc 100644 |
38 |
--- a/cnf/sets/portage.conf |
39 |
+++ b/cnf/sets/portage.conf |
40 |
@@ -9,10 +9,15 @@ |
41 |
class = portage.sets.base.DummyPackageSet |
42 |
packages = @selected @system |
43 |
|
44 |
-# Not much that could be changed for world, so better leave it alone |
45 |
[selected] |
46 |
class = portage.sets.files.WorldSelectedSet |
47 |
|
48 |
+[selected-packages] |
49 |
+class = portage.sets.files.WorldSelectedPackagesSet |
50 |
+ |
51 |
+[selected-sets] |
52 |
+class = portage.sets.files.WorldSelectedSetsSet |
53 |
+ |
54 |
# Same as for world, though later portage versions might use a different class |
55 |
[system] |
56 |
class = portage.sets.profiles.PackagesSystemSet |
57 |
diff --git a/doc/config/sets.docbook b/doc/config/sets.docbook |
58 |
index 8f74412..cf8dcf3 100644 |
59 |
--- a/doc/config/sets.docbook |
60 |
+++ b/doc/config/sets.docbook |
61 |
@@ -71,9 +71,9 @@ |
62 |
class = portage.sets.base.DummyPackageSet |
63 |
packages = @selected @system |
64 |
|
65 |
- # The selected set |
66 |
- [selected] |
67 |
- class = portage.sets.files.WorldSelectedSet |
68 |
+ # The selected-packages set |
69 |
+ [selected-packages] |
70 |
+ class = portage.sets.files.WorldSelectedPackagesSet |
71 |
|
72 |
# The classic system set |
73 |
[system] |
74 |
@@ -247,8 +247,16 @@ |
75 |
</sect3> |
76 |
</sect2> |
77 |
|
78 |
- <sect2 id='config-set-classes-WorldSelectedSet'> |
79 |
- <title>portage.sets.files.WorldSelectedSet</title> |
80 |
+ <sect2 id='config-set-classes-WorldSelectedPackagesSet'> |
81 |
+ <title>portage.sets.files.WorldSelectedPackagesSet</title> |
82 |
+ <para> |
83 |
+ A minor variation of <classname>StaticFileSet</classname>, mainly for implementation |
84 |
+ reasons. It should never be used in user configurations as it's already configured |
85 |
+ by default, doesn't support any options and will eventually be removed in a future version. |
86 |
+ </para> |
87 |
+ |
88 |
+ <sect2 id='config-set-classes-WorldSelectedSetsSet'> |
89 |
+ <title>portage.sets.files.WorldSelectedSetsSet</title> |
90 |
<para> |
91 |
A minor variation of <classname>StaticFileSet</classname>, mainly for implementation |
92 |
reasons. It should never be used in user configurations as it's already configured |
93 |
diff --git a/man/emerge.1 b/man/emerge.1 |
94 |
index a206e8e..91697b4 100644 |
95 |
--- a/man/emerge.1 |
96 |
+++ b/man/emerge.1 |
97 |
@@ -61,13 +61,15 @@ would like to query the owners of one or more files or directories. |
98 |
.TP |
99 |
.BR set |
100 |
A \fIset\fR is a convenient shorthand for a large group of |
101 |
-packages. Three sets are currently always available: \fBselected\fR, |
102 |
-\fBsystem\fR and \fBworld\fR. \fBselected\fR contains the user-selected |
103 |
-"world" packages that are listed in \fB/var/lib/portage/world\fR, |
104 |
-and nested sets that may be listed |
105 |
-in \fB/var/lib/portage/world_sets\fR. \fBsystem\fR refers to a set of |
106 |
-packages deemed necessary for your system to run properly. \fBworld\fR |
107 |
-encompasses both the \fBselected\fR and \fBsystem\fR sets. [See |
108 |
+packages. Five sets are currently always available: \fBselected-packages\fR, |
109 |
+\fBselected-sets\fR, \fBselected\fR, \fBsystem\fR and \fBworld\fR. |
110 |
+\fBselected-packages\fR contains the user-selected "world" packages that |
111 |
+are listed in \fB/var/lib/portage/world\fR, while \fBselected-sets\fR |
112 |
+contains the nested sets that may be listed in \fB/var/lib/portage/world_sets\fR. |
113 |
+\fBsystem\fR refers to a set of packages deemed necessary for your system |
114 |
+to run properly. \fBselected\fR encompasses both the \fBselected-packages\fR |
115 |
+and \fBselected-sets\fR sets, while \fBworld\fR encompasses the \fBselected\fR |
116 |
+and \fBsystem\fR sets. [See |
117 |
\fBFILES\fR below for more information.] Other sets can exist depending |
118 |
on the current configuration. The default set configuration is located |
119 |
in the \fB/usr/share/portage/config/sets\fR directory. |
120 |
diff --git a/pym/portage/_sets/__init__.py b/pym/portage/_sets/__init__.py |
121 |
index 75d1df7..a652227 100644 |
122 |
--- a/pym/portage/_sets/__init__.py |
123 |
+++ b/pym/portage/_sets/__init__.py |
124 |
@@ -121,6 +121,14 @@ class SetConfig(object): |
125 |
parser.add_section("selected") |
126 |
parser.set("selected", "class", "portage.sets.files.WorldSelectedSet") |
127 |
|
128 |
+ parser.remove_section("selected-packages") |
129 |
+ parser.add_section("selected-packages") |
130 |
+ parser.set("selected-packages", "class", "portage.sets.files.WorldSelectedPackagesSet") |
131 |
+ |
132 |
+ parser.remove_section("selected-sets") |
133 |
+ parser.add_section("selected-sets") |
134 |
+ parser.set("selected-sets", "class", "portage.sets.files.WorldSelectedSetsSet") |
135 |
+ |
136 |
parser.remove_section("system") |
137 |
parser.add_section("system") |
138 |
parser.set("system", "class", "portage.sets.profiles.PackagesSystemSet") |
139 |
diff --git a/pym/portage/_sets/files.py b/pym/portage/_sets/files.py |
140 |
index 2fb64de..e76fa83 100644 |
141 |
--- a/pym/portage/_sets/files.py |
142 |
+++ b/pym/portage/_sets/files.py |
143 |
@@ -20,7 +20,8 @@ from portage.env.loaders import ItemFileLoader, KeyListFileLoader |
144 |
from portage.env.validators import ValidAtomValidator |
145 |
from portage import cpv_getkey |
146 |
|
147 |
-__all__ = ["StaticFileSet", "ConfigFileSet", "WorldSelectedSet"] |
148 |
+__all__ = ["StaticFileSet", "ConfigFileSet", "WorldSelectedSet", |
149 |
+ "WorldSelectedPackagesSet", "WorldSelectedSetsSet"] |
150 |
|
151 |
class StaticFileSet(EditablePackageSet): |
152 |
_operations = ["merge", "unmerge"] |
153 |
@@ -205,41 +206,59 @@ class ConfigFileSet(PackageSet): |
154 |
multiBuilder = classmethod(multiBuilder) |
155 |
|
156 |
class WorldSelectedSet(EditablePackageSet): |
157 |
- description = "Set of packages that were directly installed by the user" |
158 |
- |
159 |
+ description = "Set of packages and subsets that were directly installed by the user" |
160 |
+ |
161 |
def __init__(self, eroot): |
162 |
super(WorldSelectedSet, self).__init__(allow_repo=True) |
163 |
- # most attributes exist twice as atoms and non-atoms are stored in |
164 |
- # separate files |
165 |
+ self._pkgset = WorldSelectedPackagesSet(eroot) |
166 |
+ self._setset = WorldSelectedSetsSet(eroot) |
167 |
+ |
168 |
+ def write(self): |
169 |
+ self._pkgset._atoms = self._atoms |
170 |
+ self._pkgset.write() |
171 |
+ self._setset._nonatoms = self._nonatoms |
172 |
+ self._setset.write() |
173 |
+ |
174 |
+ def load(self): |
175 |
+ self._pkgset.load() |
176 |
+ self._setset.load() |
177 |
+ self._setAtoms(self._pkgset._atoms | self._pkgset._nonatoms) |
178 |
+ |
179 |
+ def lock(self): |
180 |
+ self._pkgset.lock() |
181 |
+ self._setset.lock() |
182 |
+ |
183 |
+ def unlock(self): |
184 |
+ self._pkgset.unlock() |
185 |
+ self._setset.unlock() |
186 |
+ |
187 |
+ def cleanPackage(self, vardb, cpv): |
188 |
+ self._pkgset.cleanPackage(vardb, cpv) |
189 |
+ |
190 |
+ def singleBuilder(self, options, settings, trees): |
191 |
+ return WorldSelectedSet(settings["EROOT"]) |
192 |
+ singleBuilder = classmethod(singleBuilder) |
193 |
+ |
194 |
+class WorldSelectedPackagesSet(EditablePackageSet): |
195 |
+ description = "Set of packages that were directly installed by the user" |
196 |
+ |
197 |
+ def __init__(self, eroot): |
198 |
+ super(WorldSelectedPackagesSet, self).__init__(allow_repo=True) |
199 |
self._lock = None |
200 |
self._filename = os.path.join(eroot, WORLD_FILE) |
201 |
self.loader = ItemFileLoader(self._filename, self._validate) |
202 |
self._mtime = None |
203 |
- |
204 |
- self._filename2 = os.path.join(eroot, WORLD_SETS_FILE) |
205 |
- self.loader2 = ItemFileLoader(self._filename2, self._validate2) |
206 |
- self._mtime2 = None |
207 |
- |
208 |
+ |
209 |
def _validate(self, atom): |
210 |
return ValidAtomValidator(atom, allow_repo=True) |
211 |
|
212 |
- def _validate2(self, setname): |
213 |
- return setname.startswith(SETPREFIX) |
214 |
- |
215 |
def write(self): |
216 |
write_atomic(self._filename, |
217 |
"".join(sorted("%s\n" % x for x in self._atoms))) |
218 |
|
219 |
- write_atomic(self._filename2, |
220 |
- "".join(sorted("%s\n" % x for x in self._nonatoms))) |
221 |
- |
222 |
def load(self): |
223 |
atoms = [] |
224 |
- nonatoms = [] |
225 |
atoms_changed = False |
226 |
- # load atoms and non-atoms from different files so the worldfile is |
227 |
- # backwards-compatible with older versions and other PMs, even though |
228 |
- # it's supposed to be private state data :/ |
229 |
try: |
230 |
mtime = os.stat(self._filename).st_mtime |
231 |
except (OSError, IOError): |
232 |
@@ -261,36 +280,8 @@ class WorldSelectedSet(EditablePackageSet): |
233 |
else: |
234 |
atoms.extend(self._atoms) |
235 |
|
236 |
- changed2, nonatoms = self._load2() |
237 |
- atoms_changed |= changed2 |
238 |
- |
239 |
if atoms_changed: |
240 |
- self._setAtoms(atoms+nonatoms) |
241 |
- |
242 |
- def _load2(self): |
243 |
- changed = False |
244 |
- try: |
245 |
- mtime = os.stat(self._filename2).st_mtime |
246 |
- except (OSError, IOError): |
247 |
- mtime = None |
248 |
- if (not self._loaded or self._mtime2 != mtime): |
249 |
- try: |
250 |
- data, errors = self.loader2.load() |
251 |
- for fname in errors: |
252 |
- for e in errors[fname]: |
253 |
- self.errors.append(fname+": "+e) |
254 |
- except EnvironmentError as e: |
255 |
- if e.errno != errno.ENOENT: |
256 |
- raise |
257 |
- del e |
258 |
- data = {} |
259 |
- nonatoms = list(data) |
260 |
- self._mtime2 = mtime |
261 |
- changed = True |
262 |
- else: |
263 |
- nonatoms = list(self._nonatoms) |
264 |
- |
265 |
- return changed, nonatoms |
266 |
+ self._setAtoms(atoms) |
267 |
|
268 |
def _ensure_dirs(self): |
269 |
ensure_dirs(os.path.dirname(self._filename), gid=portage_gid, mode=0o2750, mask=0o2) |
270 |
@@ -338,5 +329,63 @@ class WorldSelectedSet(EditablePackageSet): |
271 |
self.replace(newworldlist) |
272 |
|
273 |
def singleBuilder(self, options, settings, trees): |
274 |
- return WorldSelectedSet(settings["EROOT"]) |
275 |
+ return WorldSelectedPackagesSet(settings["EROOT"]) |
276 |
+ singleBuilder = classmethod(singleBuilder) |
277 |
+ |
278 |
+class WorldSelectedSetsSet(EditablePackageSet): |
279 |
+ description = "Set of sets that were directly installed by the user" |
280 |
+ |
281 |
+ def __init__(self, eroot): |
282 |
+ super(WorldSelectedSetsSet, self).__init__(allow_repo=True) |
283 |
+ self._lock = None |
284 |
+ self._filename = os.path.join(eroot, WORLD_SETS_FILE) |
285 |
+ self.loader = ItemFileLoader(self._filename, self._validate) |
286 |
+ self._mtime = None |
287 |
+ |
288 |
+ def _validate(self, setname): |
289 |
+ return setname.startswith(SETPREFIX) |
290 |
+ |
291 |
+ def write(self): |
292 |
+ write_atomic(self._filename, |
293 |
+ "".join(sorted("%s\n" % x for x in self._nonatoms))) |
294 |
+ |
295 |
+ def load(self): |
296 |
+ atoms_changed = False |
297 |
+ try: |
298 |
+ mtime = os.stat(self._filename).st_mtime |
299 |
+ except (OSError, IOError): |
300 |
+ mtime = None |
301 |
+ if (not self._loaded or self._mtime != mtime): |
302 |
+ try: |
303 |
+ data, errors = self.loader.load() |
304 |
+ for fname in errors: |
305 |
+ for e in errors[fname]: |
306 |
+ self.errors.append(fname+": "+e) |
307 |
+ except EnvironmentError as e: |
308 |
+ if e.errno != errno.ENOENT: |
309 |
+ raise |
310 |
+ del e |
311 |
+ data = {} |
312 |
+ nonatoms = list(data) |
313 |
+ self._mtime = mtime |
314 |
+ atoms_changed = True |
315 |
+ else: |
316 |
+ nonatoms = list(self._nonatoms) |
317 |
+ |
318 |
+ if atoms_changed: |
319 |
+ self._setAtoms(nonatoms) |
320 |
+ |
321 |
+ def lock(self): |
322 |
+ if self._lock is not None: |
323 |
+ raise AssertionError("already locked") |
324 |
+ self._lock = lockfile(self._filename, wantnewlockfile=1) |
325 |
+ |
326 |
+ def unlock(self): |
327 |
+ if self._lock is None: |
328 |
+ raise AssertionError("not locked") |
329 |
+ unlockfile(self._lock) |
330 |
+ self._lock = None |
331 |
+ |
332 |
+ def singleBuilder(self, options, settings, trees): |
333 |
+ return WorldSelectedSetsSet(settings["EROOT"]) |
334 |
singleBuilder = classmethod(singleBuilder) |
335 |
-- |
336 |
2.1.3 |