1 |
Author: zmedico |
2 |
Date: 2009-04-06 22:25:15 +0000 (Mon, 06 Apr 2009) |
3 |
New Revision: 13291 |
4 |
|
5 |
Modified: |
6 |
main/trunk/man/portage.5 |
7 |
main/trunk/pym/_emerge/__init__.py |
8 |
main/trunk/pym/portage/__init__.py |
9 |
main/trunk/pym/portage/cache/metadata.py |
10 |
main/trunk/pym/portage/cache/util.py |
11 |
main/trunk/pym/portage/dbapi/porttree.py |
12 |
main/trunk/pym/portage/eclass_cache.py |
13 |
Log: |
14 |
Add portdbapi support for a metadata/layout.conf file which |
15 |
specifies information about the repository layout. Currently, |
16 |
only a single "masters" attribute is supported, which is used |
17 |
to specify names of repositories which satisfy dependencies |
18 |
on eclasses and/or ebuilds. Each repository name should |
19 |
correspond the value of a repo_name entry from one of the |
20 |
repositories that is configured via the PORTDIR or |
21 |
PORTDIR_OVERLAY variables. |
22 |
|
23 |
Since layout.conf is now used to control eclass inheritance, |
24 |
it is now safer to use overlays which contain forked eclasses |
25 |
have names identical to those from the main tree. Such |
26 |
eclasses will only apply to their containing repository and |
27 |
any other repositories which reference their containing |
28 |
repository via layout.conf. This solves bug #124041 by |
29 |
containing eclass overrides so that they don't necessarily |
30 |
apply to all ebuilds. |
31 |
|
32 |
Thanks to Alistair Bush <ali_bush@g.o> for his initial patch |
33 |
for layout.conf support in repoman (will be merged later). |
34 |
See the "QA Overlay Layout support" thread on the gentoo-dev |
35 |
mailing list for more information: |
36 |
|
37 |
http://archives.gentoo.org/gentoo-dev/msg_33c61550b4ed2b7b25dd5a4110e1ec81.xml |
38 |
|
39 |
|
40 |
Modified: main/trunk/man/portage.5 |
41 |
=================================================================== |
42 |
--- main/trunk/man/portage.5 2009-04-05 05:56:16 UTC (rev 13290) |
43 |
+++ main/trunk/man/portage.5 2009-04-06 22:25:15 UTC (rev 13291) |
44 |
@@ -59,6 +59,11 @@ |
45 |
.BR /etc/portage/profile/ |
46 |
site-specific overrides of \fB/etc/make.profile/\fR |
47 |
.TP |
48 |
+.BR /usr/portage/metadata/ |
49 |
+.nf |
50 |
+layout.conf |
51 |
+.fi |
52 |
+.TP |
53 |
.BR /usr/portage/profiles/ |
54 |
.nf |
55 |
arch.list |
56 |
@@ -543,6 +548,23 @@ |
57 |
.fi |
58 |
.RE |
59 |
.TP |
60 |
+.BR /usr/portage/metadata/ |
61 |
+.RS |
62 |
+.TP |
63 |
+.BR layout.conf |
64 |
+Specifies information about the repository layout. Currently, only a single |
65 |
+"masters" attribute is supported, which is used to specify names of |
66 |
+repositories which satisfy dependencies on eclasses and/or ebuilds. Each |
67 |
+repository name should correspond the value of a \fBrepo_name\fR entry |
68 |
+from one of the repositories that is configured via the \fBPORTDIR\fR or |
69 |
+\fBPORTDIR_OVERLAY\fR variables (see \fBmake.conf\fR(5)). |
70 |
+ |
71 |
+.I Example: |
72 |
+.nf |
73 |
+masters = gentoo java-overlay |
74 |
+.fi |
75 |
+.RE |
76 |
+.TP |
77 |
.BR /usr/portage/profiles/ |
78 |
Global Gentoo settings that are controlled by the developers. To override |
79 |
these settings, you can use the files in \fB/etc/portage/\fR. |
80 |
|
81 |
Modified: main/trunk/pym/_emerge/__init__.py |
82 |
=================================================================== |
83 |
--- main/trunk/pym/_emerge/__init__.py 2009-04-05 05:56:16 UTC (rev 13290) |
84 |
+++ main/trunk/pym/_emerge/__init__.py 2009-04-06 22:25:15 UTC (rev 13291) |
85 |
@@ -15464,41 +15464,12 @@ |
86 |
repo_name_check(trees) |
87 |
config_protect_check(trees) |
88 |
|
89 |
- eclasses_overridden = {} |
90 |
for mytrees in trees.itervalues(): |
91 |
mydb = mytrees["porttree"].dbapi |
92 |
# Freeze the portdbapi for performance (memoize all xmatch results). |
93 |
mydb.freeze() |
94 |
- eclasses_overridden.update(mydb.eclassdb._master_eclasses_overridden) |
95 |
del mytrees, mydb |
96 |
|
97 |
- if eclasses_overridden and \ |
98 |
- settings.get("PORTAGE_ECLASS_WARNING_ENABLE") != "0": |
99 |
- prefix = bad(" * ") |
100 |
- if len(eclasses_overridden) == 1: |
101 |
- writemsg(prefix + "Overlay eclass overrides " + \ |
102 |
- "eclass from PORTDIR:\n", noiselevel=-1) |
103 |
- else: |
104 |
- writemsg(prefix + "Overlay eclasses override " + \ |
105 |
- "eclasses from PORTDIR:\n", noiselevel=-1) |
106 |
- writemsg(prefix + "\n", noiselevel=-1) |
107 |
- for eclass_name in sorted(eclasses_overridden): |
108 |
- writemsg(prefix + " '%s/%s.eclass'\n" % \ |
109 |
- (eclasses_overridden[eclass_name], eclass_name), |
110 |
- noiselevel=-1) |
111 |
- writemsg(prefix + "\n", noiselevel=-1) |
112 |
- msg = "It is best to avoid overriding eclasses from PORTDIR " + \ |
113 |
- "because it will trigger invalidation of cached ebuild metadata " + \ |
114 |
- "that is distributed with the portage tree. If you must " + \ |
115 |
- "override eclasses from PORTDIR then you are advised to add " + \ |
116 |
- "FEATURES=\"metadata-transfer\" to /etc/make.conf and to run " + \ |
117 |
- "`emerge --regen` after each time that you run `emerge --sync`. " + \ |
118 |
- "Set PORTAGE_ECLASS_WARNING_ENABLE=\"0\" in /etc/make.conf if " + \ |
119 |
- "you would like to disable this warning." |
120 |
- from textwrap import wrap |
121 |
- for line in wrap(msg, 72): |
122 |
- writemsg("%s%s\n" % (prefix, line), noiselevel=-1) |
123 |
- |
124 |
if "moo" in myfiles: |
125 |
print """ |
126 |
|
127 |
|
128 |
Modified: main/trunk/pym/portage/__init__.py |
129 |
=================================================================== |
130 |
--- main/trunk/pym/portage/__init__.py 2009-04-05 05:56:16 UTC (rev 13290) |
131 |
+++ main/trunk/pym/portage/__init__.py 2009-04-06 22:25:15 UTC (rev 13291) |
132 |
@@ -1105,7 +1105,7 @@ |
133 |
"PORTAGE_BACKGROUND", |
134 |
"PORTAGE_BINHOST_CHUNKSIZE", "PORTAGE_CALLER", |
135 |
"PORTAGE_COUNTER_HASH", |
136 |
- "PORTAGE_ECLASS_WARNING_ENABLE", "PORTAGE_ELOG_CLASSES", |
137 |
+ "PORTAGE_ELOG_CLASSES", |
138 |
"PORTAGE_ELOG_MAILFROM", "PORTAGE_ELOG_MAILSUBJECT", |
139 |
"PORTAGE_ELOG_MAILURI", "PORTAGE_ELOG_SYSTEM", |
140 |
"PORTAGE_FETCH_CHECKSUM_TRY_MIRRORS", "PORTAGE_FETCH_RESUME_MIN_SIZE", |
141 |
@@ -5160,6 +5160,12 @@ |
142 |
mysettings["FILESDIR"] = pkg_dir+"/files" |
143 |
mysettings["PF"] = mypv |
144 |
|
145 |
+ if hasattr(mydbapi, '_repo_info'): |
146 |
+ mytree = os.path.dirname(os.path.dirname(pkg_dir)) |
147 |
+ repo_info = mydbapi._repo_info[mytree] |
148 |
+ mysettings['PORTDIR'] = repo_info.portdir |
149 |
+ mysettings['PORTDIR_OVERLAY'] = repo_info.portdir_overlay |
150 |
+ |
151 |
mysettings["PORTDIR"] = os.path.realpath(mysettings["PORTDIR"]) |
152 |
mysettings["DISTDIR"] = os.path.realpath(mysettings["DISTDIR"]) |
153 |
mysettings["RPMDIR"] = os.path.realpath(mysettings["RPMDIR"]) |
154 |
|
155 |
Modified: main/trunk/pym/portage/cache/metadata.py |
156 |
=================================================================== |
157 |
--- main/trunk/pym/portage/cache/metadata.py 2009-04-05 05:56:16 UTC (rev 13290) |
158 |
+++ main/trunk/pym/portage/cache/metadata.py 2009-04-06 22:25:15 UTC (rev 13291) |
159 |
@@ -29,7 +29,7 @@ |
160 |
loc = location |
161 |
super(database, self).__init__(location, *args, **config) |
162 |
self.location = os.path.join(loc, "metadata","cache") |
163 |
- self.ec = portage.eclass_cache.cache(loc) |
164 |
+ self.ec = None |
165 |
self.raise_stat_collision = False |
166 |
|
167 |
def _parse_data(self, data, cpv): |
168 |
@@ -53,9 +53,11 @@ |
169 |
|
170 |
if "_eclasses_" not in d: |
171 |
if "INHERITED" in d: |
172 |
+ if self.ec is None: |
173 |
+ self.ec = portage.eclass_cache.cache(self.location) |
174 |
try: |
175 |
d["_eclasses_"] = self.ec.get_eclass_data( |
176 |
- d["INHERITED"].split(), from_master_only=True) |
177 |
+ d["INHERITED"].split()) |
178 |
except KeyError, e: |
179 |
# INHERITED contains a non-existent eclass. |
180 |
raise cache_errors.CacheCorruption(cpv, e) |
181 |
|
182 |
Modified: main/trunk/pym/portage/cache/util.py |
183 |
=================================================================== |
184 |
--- main/trunk/pym/portage/cache/util.py 2009-04-05 05:56:16 UTC (rev 13290) |
185 |
+++ main/trunk/pym/portage/cache/util.py 2009-04-06 22:25:15 UTC (rev 13291) |
186 |
@@ -102,8 +102,7 @@ |
187 |
# Even if _eclasses_ already exists, replace it with data from |
188 |
# eclass_cache, in order to insert local eclass paths. |
189 |
try: |
190 |
- eclasses = eclass_cache.get_eclass_data(inherited, |
191 |
- from_master_only=True) |
192 |
+ eclasses = eclass_cache.get_eclass_data(inherited) |
193 |
except KeyError: |
194 |
# INHERITED contains a non-existent eclass. |
195 |
noise.eclass_stale(x) |
196 |
|
197 |
Modified: main/trunk/pym/portage/dbapi/porttree.py |
198 |
=================================================================== |
199 |
--- main/trunk/pym/portage/dbapi/porttree.py 2009-04-05 05:56:16 UTC (rev 13290) |
200 |
+++ main/trunk/pym/portage/dbapi/porttree.py 2009-04-06 22:25:15 UTC (rev 13291) |
201 |
@@ -8,7 +8,8 @@ |
202 |
portage.proxy.lazyimport.lazyimport(globals(), |
203 |
'portage.checksum', |
204 |
'portage.dep:dep_getkey,match_from_list,paren_reduce,use_reduce', |
205 |
- 'portage.util:ensure_dirs,writemsg', |
206 |
+ 'portage.env.loaders:KeyValuePairFileLoader', |
207 |
+ 'portage.util:ensure_dirs,writemsg,writemsg_level', |
208 |
'portage.versions:best,catpkgsplit,pkgsplit,ver_regexp', |
209 |
) |
210 |
|
211 |
@@ -25,7 +26,7 @@ |
212 |
listdir, dep_expand, eapi_is_supported, key_expand, dep_check, \ |
213 |
_eapi_is_deprecated |
214 |
|
215 |
-import codecs, os, stat |
216 |
+import codecs, logging, os, stat |
217 |
from itertools import izip |
218 |
|
219 |
def _src_uri_validate(cpv, eapi, src_uri): |
220 |
@@ -95,6 +96,15 @@ |
221 |
"getFetchMap(): '%s' SRC_URI arrow missing right operand" % \ |
222 |
(cpv,)) |
223 |
|
224 |
+class _repo_info(object): |
225 |
+ __slots__ = ('name', 'path', 'eclass_db', 'portdir', 'portdir_overlay') |
226 |
+ def __init__(self, name, path, eclass_db): |
227 |
+ self.name = name |
228 |
+ self.path = path |
229 |
+ self.eclass_db = eclass_db |
230 |
+ self.portdir = eclass_db.porttrees[0] |
231 |
+ self.portdir_overlay = ' '.join(eclass_db.porttrees[1:]) |
232 |
+ |
233 |
class portdbapi(dbapi): |
234 |
"""this tree will scan a portage directory located at root (passed to init)""" |
235 |
portdbapi_instances = [] |
236 |
@@ -116,10 +126,8 @@ |
237 |
# instance that is passed in. |
238 |
self.doebuild_settings = config(clone=self.mysettings) |
239 |
|
240 |
- #self.root=settings["PORTDIR"] |
241 |
+ porttree_root = os.path.realpath(porttree_root) |
242 |
self.porttree_root = porttree_root |
243 |
- if porttree_root: |
244 |
- self.porttree_root = os.path.realpath(porttree_root) |
245 |
|
246 |
self.depcachedir = os.path.realpath(self.mysettings.depcachedir) |
247 |
|
248 |
@@ -132,8 +140,7 @@ |
249 |
os.environ["SANDBOX_WRITE"] = \ |
250 |
":".join(filter(None, sandbox_write)) |
251 |
|
252 |
- self.eclassdb = eclass_cache.cache(self.porttree_root, |
253 |
- overlays=self.mysettings["PORTDIR_OVERLAY"].split()) |
254 |
+ self.eclassdb = eclass_cache.cache(porttree_root) |
255 |
|
256 |
# This is used as sanity check for aux_get(). If there is no |
257 |
# root eclass dir, we assume that PORTDIR is invalid or |
258 |
@@ -163,7 +170,43 @@ |
259 |
# don't want to see a warning every time the portage module is |
260 |
# imported. |
261 |
pass |
262 |
- |
263 |
+ |
264 |
+ self._repo_info = {} |
265 |
+ eclass_dbs = {porttree_root : self.eclassdb} |
266 |
+ for path in self.porttrees: |
267 |
+ if path in self._repo_info: |
268 |
+ continue |
269 |
+ |
270 |
+ layout_filename = os.path.join(path, "metadata/layout.conf") |
271 |
+ layout_file = KeyValuePairFileLoader(layout_filename, None, None) |
272 |
+ layout_data, layout_errors = layout_file.load() |
273 |
+ porttrees = [] |
274 |
+ for master_name in layout_data.get('masters', '').split(): |
275 |
+ master_path = self.treemap.get(master_name) |
276 |
+ if master_path is None: |
277 |
+ writemsg_level(("Unavailable repository '%s' " + \ |
278 |
+ "referenced by masters entry in '%s'\n") % \ |
279 |
+ (master_name, layout_filename), |
280 |
+ level=logging.ERROR, noiselevel=-1) |
281 |
+ else: |
282 |
+ porttrees.append(master_path) |
283 |
+ if not porttrees: |
284 |
+ porttrees.append(porttree_root) |
285 |
+ porttrees.append(path) |
286 |
+ |
287 |
+ eclass_db = None |
288 |
+ for porttree in porttrees: |
289 |
+ tree_db = eclass_dbs.get(porttree) |
290 |
+ if tree_db is None: |
291 |
+ tree_db = eclass_cache.cache(porttree) |
292 |
+ if eclass_db is None: |
293 |
+ eclass_db = tree_db.copy() |
294 |
+ else: |
295 |
+ eclass_db.append(tree_db) |
296 |
+ |
297 |
+ self._repo_info[path] = _repo_info(self._repository_map.get(path), |
298 |
+ path, eclass_db) |
299 |
+ |
300 |
self.auxdbmodule = self.mysettings.load_best_module("portdbapi.auxdbmodule") |
301 |
self.auxdb = {} |
302 |
self._pregen_auxdb = {} |
303 |
@@ -191,6 +234,10 @@ |
304 |
if os.path.isdir(os.path.join(x, "metadata", "cache")): |
305 |
self._pregen_auxdb[x] = self.metadbmodule( |
306 |
x, "metadata/cache", filtered_auxdbkeys, readonly=True) |
307 |
+ try: |
308 |
+ self._pregen_auxdb[x].ec = self._repo_info[x].eclass_db |
309 |
+ except AttributeError: |
310 |
+ pass |
311 |
# Selectively cache metadata in order to optimize dep matching. |
312 |
self._aux_cache_keys = set( |
313 |
["DEPEND", "EAPI", "INHERITED", "IUSE", "KEYWORDS", "LICENSE", |
314 |
|
315 |
Modified: main/trunk/pym/portage/eclass_cache.py |
316 |
=================================================================== |
317 |
--- main/trunk/pym/portage/eclass_cache.py 2009-04-05 05:56:16 UTC (rev 13290) |
318 |
+++ main/trunk/pym/portage/eclass_cache.py 2009-04-06 22:25:15 UTC (rev 13291) |
319 |
@@ -5,6 +5,7 @@ |
320 |
|
321 |
__all__ = ["cache"] |
322 |
|
323 |
+import warnings |
324 |
from portage.util import normalize_path, writemsg |
325 |
import errno, os, sys |
326 |
from portage.data import portage_gid |
327 |
@@ -15,19 +16,48 @@ |
328 |
Maintains the cache information about eclasses used in ebuild. |
329 |
""" |
330 |
def __init__(self, porttree_root, overlays=[]): |
331 |
- self.porttree_root = porttree_root |
332 |
|
333 |
self.eclasses = {} # {"Name": ("location","_mtime_")} |
334 |
self._eclass_locations = {} |
335 |
|
336 |
# screw with the porttree ordering, w/out having bash inherit match it, and I'll hurt you. |
337 |
# ~harring |
338 |
- self.porttrees = [self.porttree_root]+overlays |
339 |
- self.porttrees = tuple(map(normalize_path, self.porttrees)) |
340 |
- self._master_eclass_root = os.path.join(self.porttrees[0],"eclass") |
341 |
- self._master_eclasses_overridden = {} |
342 |
- self.update_eclasses() |
343 |
+ if porttree_root: |
344 |
+ self.porttree_root = porttree_root |
345 |
+ self.porttrees = [self.porttree_root] + overlays |
346 |
+ self.porttrees = tuple(map(normalize_path, self.porttrees)) |
347 |
+ self._master_eclass_root = os.path.join(self.porttrees[0], "eclass") |
348 |
+ self.update_eclasses() |
349 |
+ else: |
350 |
+ self.porttree_root = None |
351 |
+ self.porttrees = () |
352 |
+ self._master_eclass_root = None |
353 |
|
354 |
+ def copy(self): |
355 |
+ return self.__copy__() |
356 |
+ |
357 |
+ def __copy__(self): |
358 |
+ result = self.__class__(None) |
359 |
+ result.eclasses = self.eclasses.copy() |
360 |
+ result._eclass_locations = self._eclass_locations.copy() |
361 |
+ result.porttree_root = self.porttree_root |
362 |
+ result.porttrees = self.porttrees |
363 |
+ result._master_eclass_root = self._master_eclass_root |
364 |
+ return result |
365 |
+ |
366 |
+ def append(self, other): |
367 |
+ """ |
368 |
+ Append another instance to this instance. This will cause eclasses |
369 |
+ from the other instance to override and eclases from this instance |
370 |
+ that have the same name. |
371 |
+ """ |
372 |
+ if not isinstance(other, self.__class__): |
373 |
+ raise TypeError( |
374 |
+ "expected type %s, got %s" % (self.__class__, type(other))) |
375 |
+ self.porttrees = self.porttrees + other.porttrees |
376 |
+ self.eclasses.update(other.eclasses) |
377 |
+ self._eclass_locations.update(other._eclass_locations) |
378 |
+ |
379 |
def close_caches(self): |
380 |
import traceback |
381 |
traceback.print_stack() |
382 |
@@ -77,8 +107,7 @@ |
383 |
# It appears to be identical to the master, |
384 |
# so prefer the master entry. |
385 |
continue |
386 |
- else: |
387 |
- self._master_eclasses_overridden[ys] = x |
388 |
+ |
389 |
self.eclasses[ys] = (x, mtime) |
390 |
self._eclass_locations[ys] = x |
391 |
|
392 |
@@ -100,8 +129,10 @@ |
393 |
ec_dict = {} |
394 |
for x in inherits: |
395 |
ec_dict[x] = self.eclasses[x] |
396 |
- if from_master_only and \ |
397 |
- self._eclass_locations[x] != self._master_eclass_root: |
398 |
- return None |
399 |
|
400 |
+ if from_master_only is not False: |
401 |
+ warnings.warn("portage.eclass_cache.cache.get_eclass_data(): " + \ |
402 |
+ "ignoring deprecated 'from_master_only' parameter", |
403 |
+ DeprecationWarning) |
404 |
+ |
405 |
return ec_dict |