Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH] emerge --usepkgonly: propagate implicit IUSE and USE_EXPAND (bug 640318)
Date: Wed, 18 Apr 2018 01:06:13
Message-Id: 20180418010541.23920-1-zmedico@gentoo.org
1 For emerge --usepkgonly mode, it's useful to be able to operate without
2 dependence on a local ebuild repository and profile. Therefore,
3 merge Packages header settings from the binary package database
4 (including binhost(s) if enabled) into the profile configuration,
5 in order to propagate implicit IUSE and USE_EXPAND settings for use
6 with binary and installed packages. Values are appended, so the result
7 is a union of elements.
8
9 Also use ARCH from the binary package database if it's not defined by
10 the profile, since ARCH is used for validation by emerge's profile_check
11 function, and also for KEYWORDS logic in the _getmaskingstatus function.
12
13 All changes are currently confined to --usepkgonly mode, since this is
14 the mode where it is needed the most, and this ensures that behavior of
15 source-based builds is completely unaffected.
16
17 The changes only affect dependency calculations (where implicit IUSE
18 plays a role) and the user interface (display of USE_EXPAND flags).
19 The bash execution environment for binary and installed packages is
20 completely unaffected, since that environment relies on variables loaded
21 from environment.bz2 files.
22
23 Bug: https://bugs.gentoo.org/640318
24 ---
25 pym/_emerge/actions.py | 48 +++++++++++++++++--------
26 pym/_emerge/main.py | 4 ---
27 pym/portage/dbapi/bintree.py | 56 ++++++++++++++++++++++++++++++
28 pym/portage/package/ebuild/config.py | 7 ++--
29 pym/portage/package/ebuild/profile_iuse.py | 32 +++++++++++++++++
30 5 files changed, 127 insertions(+), 20 deletions(-)
31 create mode 100644 pym/portage/package/ebuild/profile_iuse.py
32
33 diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py
34 index 347ef5fbc..b90aa8cb0 100644
35 --- a/pym/_emerge/actions.py
36 +++ b/pym/_emerge/actions.py
37 @@ -78,6 +78,7 @@ from _emerge.depgraph import backtrack_depgraph, depgraph, resume_depgraph
38 from _emerge.DepPrioritySatisfiedRange import DepPrioritySatisfiedRange
39 from _emerge.emergelog import emergelog
40 from _emerge.is_valid_package_atom import is_valid_package_atom
41 +from _emerge.main import profile_check
42 from _emerge.MetadataRegen import MetadataRegen
43 from _emerge.Package import Package
44 from _emerge.ProgressHandler import ProgressHandler
45 @@ -2209,9 +2210,21 @@ def action_uninstall(settings, trees, ldpath_mtimes,
46 return rval
47
48 def adjust_configs(myopts, trees):
49 - for myroot in trees:
50 + for myroot, mytrees in trees.items():
51 mysettings = trees[myroot]["vartree"].settings
52 mysettings.unlock()
53 +
54 + # For --usepkgonly mode, propagate settings from the binary package
55 + # database, so that it's possible to operate without dependence on
56 + # a local ebuild repository and profile.
57 + if ('--usepkgonly' in myopts and
58 + mytrees['bintree']._propagate_config(mysettings)):
59 + # Also propagate changes to the portdbapi doebuild_settings
60 + # attribute which is used by Package instances for USE
61 + # calculations (in support of --binpkg-respect-use).
62 + mytrees['porttree'].dbapi.doebuild_settings = \
63 + portage.config(clone=mysettings)
64 +
65 adjust_config(myopts, mysettings)
66 mysettings.lock()
67
68 @@ -2868,7 +2881,27 @@ def run_action(emerge_config):
69 "--usepkg", "--usepkgonly"):
70 emerge_config.opts.pop(opt, None)
71
72 + # Populate the bintree with current --getbinpkg setting.
73 + # This needs to happen before:
74 + # * expand_set_arguments, in case any sets use the bintree
75 + # * adjust_configs and profile_check, in order to propagate settings
76 + # implicit IUSE and USE_EXPAND settings from the binhost(s)
77 + if (emerge_config.action in ('search', None) and
78 + '--usepkg' in emerge_config.opts):
79 + for mytrees in emerge_config.trees.values():
80 + try:
81 + mytrees['bintree'].populate(
82 + getbinpkgs='--getbinpkg' in emerge_config.opts)
83 + except ParseError as e:
84 + writemsg('\n\n!!!%s.\nSee make.conf(5) for more info.\n'
85 + % (e,), noiselevel=-1)
86 + return 1
87 +
88 adjust_configs(emerge_config.opts, emerge_config.trees)
89 +
90 + if profile_check(emerge_config.trees, emerge_config.action) != os.EX_OK:
91 + return 1
92 +
93 apply_priorities(emerge_config.target_config.settings)
94
95 if ("--autounmask-continue" in emerge_config.opts and
96 @@ -2919,19 +2952,6 @@ def run_action(emerge_config):
97 # Freeze the portdbapi for performance (memoize all xmatch results).
98 mydb.freeze()
99
100 - if emerge_config.action in ('search', None) and \
101 - "--usepkg" in emerge_config.opts:
102 - # Populate the bintree with current --getbinpkg setting.
103 - # This needs to happen before expand_set_arguments(), in case
104 - # any sets use the bintree.
105 - try:
106 - mytrees["bintree"].populate(
107 - getbinpkgs="--getbinpkg" in emerge_config.opts)
108 - except ParseError as e:
109 - writemsg("\n\n!!!%s.\nSee make.conf(5) for more info.\n"
110 - % e, noiselevel=-1)
111 - return 1
112 -
113 del mytrees, mydb
114
115 for x in emerge_config.args:
116 diff --git a/pym/_emerge/main.py b/pym/_emerge/main.py
117 index 4aa9585fa..226387495 100644
118 --- a/pym/_emerge/main.py
119 +++ b/pym/_emerge/main.py
120 @@ -1269,10 +1269,6 @@ def emerge_main(args=None):
121 except locale.Error as e:
122 writemsg_level("setlocale: %s\n" % e, level=logging.WARN)
123
124 - rval = profile_check(emerge_config.trees, emerge_config.action)
125 - if rval != os.EX_OK:
126 - return rval
127 -
128 tmpcmdline = []
129 if "--ignore-default-opts" not in myopts:
130 tmpcmdline.extend(portage.util.shlex_split(
131 diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py
132 index a963c578e..269a7b226 100644
133 --- a/pym/portage/dbapi/bintree.py
134 +++ b/pym/portage/dbapi/bintree.py
135 @@ -29,6 +29,7 @@ from portage.dep import Atom, use_reduce, paren_enclose
136 from portage.exception import AlarmSignal, InvalidData, InvalidPackageName, \
137 ParseError, PermissionDenied, PortageException
138 from portage.localization import _
139 +from portage.package.ebuild.profile_iuse import iter_iuse_vars
140 from portage import _movefile
141 from portage import os
142 from portage import _encodings
143 @@ -322,6 +323,7 @@ class binarytree(object):
144 self._pkgindex_use_evaluated_keys = \
145 ("BDEPEND", "DEPEND", "HDEPEND", "LICENSE", "RDEPEND",
146 "PDEPEND", "PROPERTIES", "RESTRICT")
147 + self._pkgindex_header = None
148 self._pkgindex_header_keys = set([
149 "ACCEPT_KEYWORDS", "ACCEPT_LICENSE",
150 "ACCEPT_PROPERTIES", "ACCEPT_RESTRICT", "CBUILD",
151 @@ -805,6 +807,10 @@ class binarytree(object):
152 pkgindex.packages.extend(iter(metadata.values()))
153 self._update_pkgindex_header(pkgindex.header)
154
155 + self._pkgindex_header = {}
156 + self._merge_pkgindex_header(pkgindex.header,
157 + self._pkgindex_header)
158 +
159 return pkgindex if update_pkgindex else None
160
161 def _populate_remote(self, getbinpkg_refresh=True):
162 @@ -1041,6 +1047,8 @@ class binarytree(object):
163 self.dbapi.cpv_inject(cpv)
164
165 self._remote_has_index = True
166 + self._merge_pkgindex_header(pkgindex.header,
167 + self._pkgindex_header)
168
169 def inject(self, cpv, filename=None):
170 """Add a freshly built package to the database. This updates
171 @@ -1292,6 +1300,54 @@ class binarytree(object):
172 inherited_keys=self._pkgindex_inherited_keys,
173 translated_keys=self._pkgindex_translated_keys)
174
175 + @staticmethod
176 + def _merge_pkgindex_header(src, dest):
177 + """
178 + Merge Packages header settings from src to dest, in order to
179 + propagate implicit IUSE and USE_EXPAND settings for use with
180 + binary and installed packages. Values are appended, so the
181 + result is a union of elements from src and dest.
182 +
183 + Pull in ARCH if it's not defined, since it's used for validation
184 + by emerge's profile_check function, and also for KEYWORDS logic
185 + in the _getmaskingstatus function.
186 +
187 + @param src: source mapping (read only)
188 + @type src: Mapping
189 + @param dest: destination mapping
190 + @type dest: MutableMapping
191 + """
192 + for k, v in iter_iuse_vars(src):
193 + v_before = dest.get(k)
194 + if v_before is not None:
195 + v = v_before + ' ' + v
196 + dest[k] = v
197 +
198 + if 'ARCH' not in dest and 'ARCH' in src:
199 + dest['ARCH'] = src['ARCH']
200 +
201 + def _propagate_config(self, config):
202 + """
203 + Propagate implicit IUSE and USE_EXPAND settings from the binary
204 + package database to a config instance. If settings are not
205 + available to propagate, then this will do nothing and return
206 + False.
207 +
208 + @param config: config instance
209 + @type config: portage.config
210 + @rtype: bool
211 + @return: True if settings successfully propagated, False if settings
212 + were not available to propagate.
213 + """
214 + if self._pkgindex_header is None:
215 + return False
216 +
217 + self._merge_pkgindex_header(self._pkgindex_header,
218 + config.configdict['defaults'])
219 + config.regenerate()
220 + config._init_iuse()
221 + return True
222 +
223 def _update_pkgindex_header(self, header):
224 """
225 Add useful settings to the Packages file header, for use by
226 diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py
227 index a32892e94..071385684 100644
228 --- a/pym/portage/package/ebuild/config.py
229 +++ b/pym/portage/package/ebuild/config.py
230 @@ -943,8 +943,7 @@ class config(object):
231 if bsd_chflags:
232 self.features.add('chflags')
233
234 - self._iuse_effective = self._calc_iuse_effective()
235 - self._iuse_implicit_match = _iuse_implicit_match_cache(self)
236 + self._init_iuse()
237
238 self._validate_commands()
239
240 @@ -961,6 +960,10 @@ class config(object):
241 if mycpv:
242 self.setcpv(mycpv)
243
244 + def _init_iuse(self):
245 + self._iuse_effective = self._calc_iuse_effective()
246 + self._iuse_implicit_match = _iuse_implicit_match_cache(self)
247 +
248 @property
249 def mygcfg(self):
250 warnings.warn("portage.config.mygcfg is deprecated", stacklevel=3)
251 diff --git a/pym/portage/package/ebuild/profile_iuse.py b/pym/portage/package/ebuild/profile_iuse.py
252 new file mode 100644
253 index 000000000..d3f201e54
254 --- /dev/null
255 +++ b/pym/portage/package/ebuild/profile_iuse.py
256 @@ -0,0 +1,32 @@
257 +# Copyright 2018 Gentoo Foundation
258 +# Distributed under the terms of the GNU General Public License v2
259 +
260 +__all__ = (
261 + 'iter_iuse_vars',
262 +)
263 +
264 +
265 +def iter_iuse_vars(env):
266 + """
267 + Iterate over (key, value) pairs of profile variables that contribute
268 + to implicit IUSE for EAPI 5 and later.
269 +
270 + @param env: Ebuild environment
271 + @type env: Mapping
272 + @rtype: iterator
273 + @return: iterator over (key, value) pairs of profile variables
274 + """
275 +
276 + for k in ('IUSE_IMPLICIT', 'USE_EXPAND_IMPLICIT', 'USE_EXPAND_UNPREFIXED', 'USE_EXPAND'):
277 + v = env.get(k)
278 + if v is not None:
279 + yield (k, v)
280 +
281 + use_expand_implicit = frozenset(env.get('USE_EXPAND_IMPLICIT', '').split())
282 +
283 + for v in env.get('USE_EXPAND_UNPREFIXED', '').split() + env.get('USE_EXPAND', '').split():
284 + if v in use_expand_implicit:
285 + k = 'USE_EXPAND_VALUES_' + v
286 + v = env.get(k)
287 + if v is not None:
288 + yield (k, v)
289 --
290 2.13.6