Gentoo Archives: gentoo-commits

From: "Zac Medico (zmedico)" <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r13462 - in main/branches/2.1.6: man pym/_emerge pym/portage pym/portage/cache pym/portage/dbapi
Date: Thu, 30 Apr 2009 06:58:32
Message-Id: E1LzQE1-0005uu-RN@stork.gentoo.org
1 Author: zmedico
2 Date: 2009-04-30 06:58:28 +0000 (Thu, 30 Apr 2009)
3 New Revision: 13462
4
5 Modified:
6 main/branches/2.1.6/man/portage.5
7 main/branches/2.1.6/pym/_emerge/__init__.py
8 main/branches/2.1.6/pym/portage/__init__.py
9 main/branches/2.1.6/pym/portage/cache/metadata.py
10 main/branches/2.1.6/pym/portage/cache/util.py
11 main/branches/2.1.6/pym/portage/dbapi/porttree.py
12 main/branches/2.1.6/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 (trunk r13291)
39
40 Modified: main/branches/2.1.6/man/portage.5
41 ===================================================================
42 --- main/branches/2.1.6/man/portage.5 2009-04-30 06:58:14 UTC (rev 13461)
43 +++ main/branches/2.1.6/man/portage.5 2009-04-30 06:58:28 UTC (rev 13462)
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 @@ -542,6 +547,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/branches/2.1.6/pym/_emerge/__init__.py
82 ===================================================================
83 --- main/branches/2.1.6/pym/_emerge/__init__.py 2009-04-30 06:58:14 UTC (rev 13461)
84 +++ main/branches/2.1.6/pym/_emerge/__init__.py 2009-04-30 06:58:28 UTC (rev 13462)
85 @@ -14977,41 +14977,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/branches/2.1.6/pym/portage/__init__.py
129 ===================================================================
130 --- main/branches/2.1.6/pym/portage/__init__.py 2009-04-30 06:58:14 UTC (rev 13461)
131 +++ main/branches/2.1.6/pym/portage/__init__.py 2009-04-30 06:58:28 UTC (rev 13462)
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 @@ -5150,6 +5150,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/branches/2.1.6/pym/portage/cache/metadata.py
156 ===================================================================
157 --- main/branches/2.1.6/pym/portage/cache/metadata.py 2009-04-30 06:58:14 UTC (rev 13461)
158 +++ main/branches/2.1.6/pym/portage/cache/metadata.py 2009-04-30 06:58:28 UTC (rev 13462)
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/branches/2.1.6/pym/portage/cache/util.py
183 ===================================================================
184 --- main/branches/2.1.6/pym/portage/cache/util.py 2009-04-30 06:58:14 UTC (rev 13461)
185 +++ main/branches/2.1.6/pym/portage/cache/util.py 2009-04-30 06:58:28 UTC (rev 13462)
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/branches/2.1.6/pym/portage/dbapi/porttree.py
198 ===================================================================
199 --- main/branches/2.1.6/pym/portage/dbapi/porttree.py 2009-04-30 06:58:14 UTC (rev 13461)
200 +++ main/branches/2.1.6/pym/portage/dbapi/porttree.py 2009-04-30 06:58:28 UTC (rev 13462)
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/branches/2.1.6/pym/portage/eclass_cache.py
316 ===================================================================
317 --- main/branches/2.1.6/pym/portage/eclass_cache.py 2009-04-30 06:58:14 UTC (rev 13461)
318 +++ main/branches/2.1.6/pym/portage/eclass_cache.py 2009-04-30 06:58:28 UTC (rev 13462)
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