Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: pym/_emerge/resolver/, pym/_emerge/, pym/portage/, pym/portage/dbapi/
Date: Mon, 09 Apr 2018 05:21:17
Message-Id: 1523251195.bfe7892202b85c46ff127048ca1cc752c54b186c.zmedico@gentoo
1 commit: bfe7892202b85c46ff127048ca1cc752c54b186c
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Fri Apr 6 20:05:25 2018 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Mon Apr 9 05:19:55 2018 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=bfe78922
7
8 _pkg_str: add _db attribute (bug 640318)
9
10 In order to propagate information from dbapi to Package instance,
11 it's useful for each _pkg_str instance to have a _db attribute
12 which references the dbapi instance that instantiated it. Use a new
13 dbapi._iuse_implicit_cnstr method to delegate implicit IUSE logic to
14 the dbapi instance, in order to make the behavior customizable at the
15 dbapi level for the purposes of bug 640318. This patch consists only
16 of refactoring, with no behavioral changes.
17
18 Bug: https://bugs.gentoo.org/640318
19
20 pym/_emerge/Package.py | 53 +++++++++---------------------
21 pym/_emerge/depgraph.py | 11 ++++++-
22 pym/_emerge/resolver/DbapiProvidesIndex.py | 3 +-
23 pym/portage/dbapi/__init__.py | 44 +++++++++++++++++++++----
24 pym/portage/dbapi/bintree.py | 15 +++++----
25 pym/portage/dbapi/porttree.py | 4 +--
26 pym/portage/dbapi/vartree.py | 5 +--
27 pym/portage/dbapi/virtual.py | 4 +--
28 pym/portage/versions.py | 6 ++--
29 9 files changed, 84 insertions(+), 61 deletions(-)
30
31 diff --git a/pym/_emerge/Package.py b/pym/_emerge/Package.py
32 index 791a35612..a7ce00bc9 100644
33 --- a/pym/_emerge/Package.py
34 +++ b/pym/_emerge/Package.py
35 @@ -67,8 +67,19 @@ class Package(Task):
36 if not self.built:
37 self._metadata['CHOST'] = self.root_config.settings.get('CHOST', '')
38 eapi_attrs = _get_eapi_attrs(self.eapi)
39 +
40 + try:
41 + db = self.cpv._db
42 + except AttributeError:
43 + if self.built:
44 + # For independence from the source ebuild repository and
45 + # profile implicit IUSE state, require the _db attribute
46 + # for built packages.
47 + raise
48 + db = self.root_config.trees['porttree'].dbapi
49 +
50 self.cpv = _pkg_str(self.cpv, metadata=self._metadata,
51 - settings=self.root_config.settings)
52 + settings=self.root_config.settings, db=db)
53 if hasattr(self.cpv, 'slot_invalid'):
54 self._invalid_metadata('SLOT.invalid',
55 "SLOT: invalid value: '%s'" % self._metadata["SLOT"])
56 @@ -82,17 +93,10 @@ class Package(Task):
57 # sync metadata with validated repo (may be UNKNOWN_REPO)
58 self._metadata['repository'] = self.cpv.repo
59
60 - if eapi_attrs.iuse_effective:
61 - implicit_match = self.root_config.settings._iuse_effective_match
62 - if self.built:
63 - implicit_match = functools.partial(
64 - self._built_iuse_effective_match,
65 - implicit_match, frozenset(self._metadata['USE'].split()))
66 - else:
67 - implicit_match = self.root_config.settings._iuse_implicit_match
68 + implicit_match = db._iuse_implicit_cnstr(self.cpv, self._metadata)
69 usealiases = self.root_config.settings._use_manager.getUseAliases(self)
70 - self.iuse = self._iuse(self, self._metadata["IUSE"].split(), implicit_match,
71 - usealiases, self.eapi)
72 + self.iuse = self._iuse(self, self._metadata["IUSE"].split(),
73 + implicit_match, usealiases, self.eapi)
74
75 if (self.iuse.enabled or self.iuse.disabled) and \
76 not eapi_attrs.iuse_defaults:
77 @@ -115,33 +119,6 @@ class Package(Task):
78 type_name=self.type_name)
79 self._hash_value = hash(self._hash_key)
80
81 - @staticmethod
82 - def _built_iuse_effective_match(prof_effective_match, built_use, flag):
83 - """
84 - For built packages, it is desirable for the built USE setting to be
85 - independent of the profile's current IUSE_IMPLICIT state, since the
86 - profile's IUSE_IMPLICT setting may have diverged. Therefore, any
87 - member of the built USE setting is considered to be a valid member of
88 - IUSE_EFFECTIVE. Note that the binary package may be remote, so it's
89 - only possible to rely on metadata that is available in the remote
90 - Packages file, and the IUSE_IMPLICIT header in the Packages file is
91 - vulnerable to mutation (see bug 640318).
92 -
93 - This function is only used for EAPIs that support IUSE_EFFECTIVE,
94 - since built USE settings for earlier EAPIs may contain a large
95 - number of irrelevant flags.
96 -
97 - @param prof_effective_match: function to match IUSE_EFFECTIVE
98 - values for the current profile
99 - @type prof_effective_match: callable
100 - @param built_use: built USE setting
101 - @type built_use: frozenset
102 - @return: True if flag is a valid USE value which may
103 - be specified in USE dependencies, False otherwise.
104 - @rtype: bool
105 - """
106 - return flag in built_use or prof_effective_match(flag)
107 -
108 @property
109 def eapi(self):
110 return self._metadata["EAPI"]
111
112 diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
113 index 963bf25f4..160ea5e94 100644
114 --- a/pym/_emerge/depgraph.py
115 +++ b/pym/_emerge/depgraph.py
116 @@ -50,7 +50,7 @@ from portage.util.digraph import digraph
117 from portage.util._async.TaskScheduler import TaskScheduler
118 from portage.util._eventloop.EventLoop import EventLoop
119 from portage.util._eventloop.global_event_loop import global_event_loop
120 -from portage.versions import catpkgsplit
121 +from portage.versions import _pkg_str, catpkgsplit
122
123 from _emerge.AtomArg import AtomArg
124 from _emerge.Blocker import Blocker
125 @@ -6975,6 +6975,15 @@ class depgraph(object):
126 except KeyError:
127 raise portage.exception.PackageNotFound(cpv)
128
129 + # Ensure that this cpv is linked to the correct db, since the
130 + # caller might have passed in a cpv from a different db, in
131 + # order get an instance from this db with the same cpv.
132 + # If db has a _db attribute, use that instead, in order to
133 + # to use the underlying db of DbapiProvidesIndex or similar.
134 + db = getattr(db, '_db', db)
135 + if getattr(cpv, '_db', None) is not db:
136 + cpv = _pkg_str(cpv, db=db)
137 +
138 pkg = Package(built=(type_name != "ebuild"), cpv=cpv,
139 installed=installed, metadata=metadata, onlydeps=onlydeps,
140 root_config=root_config, type_name=type_name)
141
142 diff --git a/pym/_emerge/resolver/DbapiProvidesIndex.py b/pym/_emerge/resolver/DbapiProvidesIndex.py
143 index 59ae71941..1650edd4e 100644
144 --- a/pym/_emerge/resolver/DbapiProvidesIndex.py
145 +++ b/pym/_emerge/resolver/DbapiProvidesIndex.py
146 @@ -24,7 +24,8 @@ class DbapiProvidesIndex(object):
147 _copy_attrs = ('aux_get', 'aux_update', 'categories', 'cpv_all',
148 'cpv_exists', 'cp_all', 'cp_list', 'getfetchsizes',
149 'settings', '_aux_cache_keys', '_clear_cache',
150 - '_cpv_sort_ascending', '_pkg_str', '_pkg_str_aux_keys')
151 + '_cpv_sort_ascending', '_iuse_implicit_cnstr', '_pkg_str',
152 + '_pkg_str_aux_keys')
153
154 def __init__(self, db):
155 self._db = db
156
157 diff --git a/pym/portage/dbapi/__init__.py b/pym/portage/dbapi/__init__.py
158 index c1b5d967d..d320cc75f 100644
159 --- a/pym/portage/dbapi/__init__.py
160 +++ b/pym/portage/dbapi/__init__.py
161 @@ -166,7 +166,7 @@ class dbapi(object):
162 metadata = dict(zip(self._pkg_str_aux_keys,
163 self.aux_get(cpv, self._pkg_str_aux_keys, myrepo=repo)))
164
165 - return _pkg_str(cpv, metadata=metadata, settings=self.settings)
166 + return _pkg_str(cpv, metadata=metadata, settings=self.settings, db=self)
167
168 def _iter_match_repo(self, atom, cpv_iter):
169 for cpv in cpv_iter:
170 @@ -216,16 +216,48 @@ class dbapi(object):
171
172 yield cpv
173
174 - def _match_use(self, atom, pkg, metadata, ignore_profile=False):
175 + def _iuse_implicit_cnstr(self, pkg, metadata):
176 + """
177 + Construct a callable that checks if a given USE flag should
178 + be considered to be a member of the implicit IUSE for the
179 + given package.
180 +
181 + @param pkg: package
182 + @type pkg: _pkg_str
183 + @param metadata: package metadata
184 + @type metadata: Mapping
185 + @return: a callable that accepts a single USE flag argument,
186 + and returns True only if the USE flag should be considered
187 + to be a member of the implicit IUSE for the given package.
188 + @rtype: callable
189 + """
190 eapi_attrs = _get_eapi_attrs(metadata["EAPI"])
191 if eapi_attrs.iuse_effective:
192 iuse_implicit_match = self.settings._iuse_effective_match
193 - if not self._use_mutable:
194 - iuse_implicit_match = functools.partial(
195 - Package._built_iuse_effective_match,
196 - iuse_implicit_match, frozenset(metadata["USE"].split()))
197 else:
198 iuse_implicit_match = self.settings._iuse_implicit_match
199 +
200 + if not self._use_mutable and eapi_attrs.iuse_effective:
201 + # For built packages, it is desirable for the built USE setting to
202 + # be independent of the profile's current IUSE_IMPLICIT state, since
203 + # the profile's IUSE_IMPLICT setting may have diverged. Therefore,
204 + # any member of the built USE setting is considered to be a valid
205 + # member of IUSE_EFFECTIVE. Note that the binary package may be
206 + # remote, so it's only possible to rely on metadata that is available
207 + # in the remote Packages file, and the IUSE_IMPLICIT header in the
208 + # Packages file is vulnerable to mutation (see bug 640318).
209 + #
210 + # This behavior is only used for EAPIs that support IUSE_EFFECTIVE,
211 + # since built USE settings for earlier EAPIs may contain a large
212 + # number of irrelevant flags.
213 + prof_iuse = iuse_implicit_match
214 + enabled = frozenset(metadata["USE"].split()).__contains__
215 + iuse_implicit_match = lambda flag: prof_iuse(flag) or enabled(flag)
216 +
217 + return iuse_implicit_match
218 +
219 + def _match_use(self, atom, pkg, metadata, ignore_profile=False):
220 + iuse_implicit_match = self._iuse_implicit_cnstr(pkg, metadata)
221 usealiases = self.settings._use_manager.getUseAliases(pkg)
222 iuse = Package._iuse(None, metadata["IUSE"].split(), iuse_implicit_match, usealiases, metadata["EAPI"])
223
224
225 diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py
226 index fc48a6902..42d334d24 100644
227 --- a/pym/portage/dbapi/bintree.py
228 +++ b/pym/portage/dbapi/bintree.py
229 @@ -458,7 +458,7 @@ class binarytree(object):
230 if v is not None:
231 v = _unicode_decode(v)
232 metadata[k] = " ".join(v.split())
233 - mynewcpv = _pkg_str(mynewcpv, metadata=metadata)
234 + mynewcpv = _pkg_str(mynewcpv, metadata=metadata, db=self.dbapi)
235 new_path = self.getname(mynewcpv)
236 self._pkg_paths[
237 self.dbapi._instance_key(mynewcpv)] = new_path[len(self.pkgdir)+1:]
238 @@ -589,7 +589,7 @@ class binarytree(object):
239 basename_index = {}
240 for d in pkgindex.packages:
241 cpv = _pkg_str(d["CPV"], metadata=d,
242 - settings=self.settings)
243 + settings=self.settings, db=self.dbapi)
244 d["CPV"] = cpv
245 metadata[_instance_key(cpv)] = d
246 path = d.get("PATH")
247 @@ -755,8 +755,8 @@ class binarytree(object):
248 pkg_metadata.pop("CATEGORY")
249 pkg_metadata.pop("PF")
250 mycpv = _pkg_str(mycpv,
251 - metadata=self.dbapi._aux_cache_slot_dict(
252 - pkg_metadata))
253 + metadata=self.dbapi._aux_cache_slot_dict(pkg_metadata),
254 + db=self.dbapi)
255 pkg_paths[_instance_key(mycpv)] = mypath
256 self.dbapi.cpv_inject(mycpv)
257 update_pkgindex = True
258 @@ -1028,7 +1028,7 @@ class binarytree(object):
259 remote_base_uri = pkgindex.header.get("URI", base_url)
260 for d in pkgindex.packages:
261 cpv = _pkg_str(d["CPV"], metadata=d,
262 - settings=self.settings)
263 + settings=self.settings, db=self.dbapi)
264 # Local package instances override remote instances
265 # with the same instance_key.
266 if self.dbapi.cpv_exists(cpv):
267 @@ -1097,7 +1097,8 @@ class binarytree(object):
268 if self._remotepkgs is not None:
269 fetched = self._remotepkgs.pop(instance_key, None)
270
271 - cpv = _pkg_str(cpv, metadata=metadata, settings=self.settings)
272 + cpv = _pkg_str(cpv, metadata=metadata, settings=self.settings,
273 + db=self.dbapi)
274
275 # Reread the Packages index (in case it's been changed by another
276 # process) and then updated it, all while holding a lock.
277 @@ -1128,7 +1129,7 @@ class binarytree(object):
278 build_id = self._parse_build_id(basename)
279 metadata["BUILD_ID"] = _unicode(build_id)
280 cpv = _pkg_str(cpv, metadata=metadata,
281 - settings=self.settings)
282 + settings=self.settings, db=self.dbapi)
283 binpkg = portage.xpak.tbz2(full_path)
284 binary_data = binpkg.get_data()
285 binary_data[b"BUILD_ID"] = _unicode_encode(
286
287 diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py
288 index 69e14dbcd..910e90e6f 100644
289 --- a/pym/portage/dbapi/porttree.py
290 +++ b/pym/portage/dbapi/porttree.py
291 @@ -945,7 +945,7 @@ class portdbapi(dbapi):
292 writemsg(_("\nInvalid ebuild version: %s\n") % \
293 os.path.join(oroot, mycp, x), noiselevel=-1)
294 continue
295 - d[_pkg_str(mysplit[0]+"/"+pf)] = None
296 + d[_pkg_str(mysplit[0]+"/"+pf, db=self)] = None
297 if invalid_category and d:
298 writemsg(_("\n!!! '%s' has a category that is not listed in " \
299 "%setc/portage/categories\n") % \
300 @@ -1070,7 +1070,7 @@ class portdbapi(dbapi):
301
302 try:
303 pkg_str = _pkg_str(cpv, metadata=metadata,
304 - settings=self.settings)
305 + settings=self.settings, db=self)
306 except InvalidData:
307 continue
308
309
310 diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
311 index a136c38f1..c274248e3 100644
312 --- a/pym/portage/dbapi/vartree.py
313 +++ b/pym/portage/dbapi/vartree.py
314 @@ -466,7 +466,8 @@ class vardbapi(dbapi):
315 cpv = "%s/%s" % (mysplit[0], x)
316 metadata = dict(zip(self._aux_cache_keys,
317 self.aux_get(cpv, self._aux_cache_keys)))
318 - returnme.append(_pkg_str(cpv, metadata=metadata))
319 + returnme.append(_pkg_str(cpv, metadata=metadata,
320 + settings=self.settings, db=self))
321 self._cpv_sort_ascending(returnme)
322 if use_cache:
323 self.cpcache[mycp] = [mystat, returnme[:]]
324 @@ -520,7 +521,7 @@ class vardbapi(dbapi):
325 subpath = x + "/" + y
326 # -MERGING- should never be a cpv, nor should files.
327 try:
328 - subpath = _pkg_str(subpath)
329 + subpath = _pkg_str(subpath, db=self)
330 except InvalidData:
331 self.invalidentry(self.getpath(subpath))
332 continue
333
334 diff --git a/pym/portage/dbapi/virtual.py b/pym/portage/dbapi/virtual.py
335 index f2e841fcd..3f7e6c221 100644
336 --- a/pym/portage/dbapi/virtual.py
337 +++ b/pym/portage/dbapi/virtual.py
338 @@ -151,10 +151,10 @@ class fakedbapi(dbapi):
339 if mycp is None or \
340 (myslot is None and metadata is not None and metadata.get('SLOT')):
341 if metadata is None:
342 - mycpv = _pkg_str(mycpv)
343 + mycpv = _pkg_str(mycpv, db=self)
344 else:
345 mycpv = _pkg_str(mycpv, metadata=metadata,
346 - settings=self.settings)
347 + settings=self.settings, db=self)
348
349 mycp = mycpv.cp
350 try:
351
352 diff --git a/pym/portage/versions.py b/pym/portage/versions.py
353 index 7b6a57673..0c21373cc 100644
354 --- a/pym/portage/versions.py
355 +++ b/pym/portage/versions.py
356 @@ -363,12 +363,12 @@ class _pkg_str(_unicode):
357
358 def __new__(cls, cpv, metadata=None, settings=None, eapi=None,
359 repo=None, slot=None, build_time=None, build_id=None,
360 - file_size=None, mtime=None):
361 + file_size=None, mtime=None, db=None):
362 return _unicode.__new__(cls, cpv)
363
364 def __init__(self, cpv, metadata=None, settings=None, eapi=None,
365 repo=None, slot=None, build_time=None, build_id=None,
366 - file_size=None, mtime=None):
367 + file_size=None, mtime=None, db=None):
368 if not isinstance(cpv, _unicode):
369 # Avoid TypeError from _unicode.__init__ with PyPy.
370 cpv = _unicode_decode(cpv)
371 @@ -384,6 +384,8 @@ class _pkg_str(_unicode):
372 mtime = metadata.get('_mtime_', mtime)
373 if settings is not None:
374 self.__dict__['_settings'] = settings
375 + if db is not None:
376 + self.__dict__['_db'] = db
377 if eapi is not None:
378 self.__dict__['eapi'] = eapi