| Trees | Indices | Help |
|
|---|
|
|
1 # Copyright 1999-2013 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 from __future__ import print_function, unicode_literals
5
6 import errno
7 import io
8 import logging
9 import stat
10 import sys
11 import textwrap
12 import warnings
13 from collections import deque
14 from itertools import chain
15
16 import portage
17 from portage import os, OrderedDict
18 from portage import _unicode_decode, _unicode_encode, _encodings
19 from portage.const import PORTAGE_PACKAGE_ATOM, USER_CONFIG_PATH, VCS_DIRS
20 from portage.dbapi import dbapi
21 from portage.dbapi.dep_expand import dep_expand
22 from portage.dbapi._similar_name_search import similar_name_search
23 from portage.dep import Atom, best_match_to_list, extract_affecting_use, \
24 check_required_use, human_readable_required_use, match_from_list, \
25 _repo_separator
26 from portage.dep._slot_operator import ignore_built_slot_operator_deps
27 from portage.eapi import eapi_has_strong_blocks, eapi_has_required_use, \
28 _get_eapi_attrs
29 from portage.exception import (InvalidAtom, InvalidData, InvalidDependString,
30 PackageNotFound, PortageException)
31 from portage.output import colorize, create_color_func, \
32 darkgreen, green
33 bad = create_color_func("BAD")
34 from portage.package.ebuild.config import _get_feature_flags
35 from portage.package.ebuild.getmaskingstatus import \
36 _getmaskingstatus, _MaskReason
37 from portage._sets import SETPREFIX
38 from portage._sets.base import InternalPackageSet
39 from portage.util import ConfigProtect, shlex_split, new_protect_filename
40 from portage.util import cmp_sort_key, writemsg, writemsg_stdout
41 from portage.util import ensure_dirs
42 from portage.util import writemsg_level, write_atomic
43 from portage.util.digraph import digraph
44 from portage.util._async.TaskScheduler import TaskScheduler
45 from portage.util._eventloop.EventLoop import EventLoop
46 from portage.util._eventloop.global_event_loop import global_event_loop
47 from portage.versions import catpkgsplit
48
49 from _emerge.AtomArg import AtomArg
50 from _emerge.Blocker import Blocker
51 from _emerge.BlockerCache import BlockerCache
52 from _emerge.BlockerDepPriority import BlockerDepPriority
53 from .chk_updated_cfg_files import chk_updated_cfg_files
54 from _emerge.countdown import countdown
55 from _emerge.create_world_atom import create_world_atom
56 from _emerge.Dependency import Dependency
57 from _emerge.DependencyArg import DependencyArg
58 from _emerge.DepPriority import DepPriority
59 from _emerge.DepPriorityNormalRange import DepPriorityNormalRange
60 from _emerge.DepPrioritySatisfiedRange import DepPrioritySatisfiedRange
61 from _emerge.EbuildMetadataPhase import EbuildMetadataPhase
62 from _emerge.FakeVartree import FakeVartree
63 from _emerge._find_deep_system_runtime_deps import _find_deep_system_runtime_deps
64 from _emerge.is_valid_package_atom import insert_category_into_atom, \
65 is_valid_package_atom
66 from _emerge.Package import Package
67 from _emerge.PackageArg import PackageArg
68 from _emerge.PackageVirtualDbapi import PackageVirtualDbapi
69 from _emerge.RootConfig import RootConfig
70 from _emerge.search import search
71 from _emerge.SetArg import SetArg
72 from _emerge.show_invalid_depstring_notice import show_invalid_depstring_notice
73 from _emerge.UnmergeDepPriority import UnmergeDepPriority
74 from _emerge.UseFlagDisplay import pkg_use_display
75 from _emerge.userquery import userquery
76
77 from _emerge.resolver.backtracking import Backtracker, BacktrackParameter
78 from _emerge.resolver.slot_collision import slot_conflict_handler
79 from _emerge.resolver.circular_dependency import circular_dependency_handler
80 from _emerge.resolver.output import Display
81
82 if sys.hexversion >= 0x3000000:
83 basestring = str
84 long = int
85 _unicode = str
86 else:
87 _unicode = unicode
88
95
97 pkgs = InternalPackageSet(allow_wildcard=True)
98 for x in atoms:
99 try:
100 x = Atom(x, allow_wildcard=True, allow_repo=False)
101 except portage.exception.InvalidAtom:
102 x = Atom("*/" + x, allow_wildcard=True, allow_repo=False)
103 pkgs.add(x)
104 return pkgs
105
107
109 self.settings = settings
110 self.target_root = settings["EROOT"]
111 self.myopts = myopts
112 self.edebug = 0
113 if settings.get("PORTAGE_DEBUG", "") == "1":
114 self.edebug = 1
115 self.spinner = spinner
116 self._running_root = trees[trees._running_eroot]["root_config"]
117 self.pkgsettings = {}
118 self.trees = {}
119 self._trees_orig = trees
120 self.roots = {}
121 # All Package instances
122 self._pkg_cache = {}
123 self._highest_license_masked = {}
124 dynamic_deps = myopts.get("--dynamic-deps", "y") != "n"
125 ignore_built_slot_operator_deps = myopts.get(
126 "--ignore-built-slot-operator-deps", "n") == "y"
127 for myroot in trees:
128 self.trees[myroot] = {}
129 # Create a RootConfig instance that references
130 # the FakeVartree instead of the real one.
131 self.roots[myroot] = RootConfig(
132 trees[myroot]["vartree"].settings,
133 self.trees[myroot],
134 trees[myroot]["root_config"].setconfig)
135 for tree in ("porttree", "bintree"):
136 self.trees[myroot][tree] = trees[myroot][tree]
137 self.trees[myroot]["vartree"] = \
138 FakeVartree(trees[myroot]["root_config"],
139 pkg_cache=self._pkg_cache,
140 pkg_root_config=self.roots[myroot],
141 dynamic_deps=dynamic_deps,
142 ignore_built_slot_operator_deps=ignore_built_slot_operator_deps)
143 self.pkgsettings[myroot] = portage.config(
144 clone=self.trees[myroot]["vartree"].settings)
145
146 self._required_set_names = set(["world"])
147
148 atoms = ' '.join(myopts.get("--exclude", [])).split()
149 self.excluded_pkgs = _wildcard_set(atoms)
150 atoms = ' '.join(myopts.get("--reinstall-atoms", [])).split()
151 self.reinstall_atoms = _wildcard_set(atoms)
152 atoms = ' '.join(myopts.get("--usepkg-exclude", [])).split()
153 self.usepkg_exclude = _wildcard_set(atoms)
154 atoms = ' '.join(myopts.get("--useoldpkg-atoms", [])).split()
155 self.useoldpkg_atoms = _wildcard_set(atoms)
156 atoms = ' '.join(myopts.get("--rebuild-exclude", [])).split()
157 self.rebuild_exclude = _wildcard_set(atoms)
158 atoms = ' '.join(myopts.get("--rebuild-ignore", [])).split()
159 self.rebuild_ignore = _wildcard_set(atoms)
160
161 self.rebuild_if_new_rev = "--rebuild-if-new-rev" in myopts
162 self.rebuild_if_new_ver = "--rebuild-if-new-ver" in myopts
163 self.rebuild_if_unbuilt = "--rebuild-if-unbuilt" in myopts
164
167 # contains all sets added to the graph
168 self.sets = {}
169 # contains non-set atoms given as arguments
170 self.sets['__non_set_args__'] = InternalPackageSet(allow_repo=True)
171 # contains all atoms from all sets added to the graph, including
172 # atoms given as arguments
173 self.atoms = InternalPackageSet(allow_repo=True)
174 self.atom_arg_map = {}
175
178 self._graph = digraph()
179 self._frozen_config = frozen_config
180 self.rebuild_list = backtrack_parameters.rebuild_list.copy()
181 self.orig_rebuild_list = self.rebuild_list.copy()
182 self.reinstall_list = backtrack_parameters.reinstall_list.copy()
183 self.rebuild_if_new_rev = frozen_config.rebuild_if_new_rev
184 self.rebuild_if_new_ver = frozen_config.rebuild_if_new_ver
185 self.rebuild_if_unbuilt = frozen_config.rebuild_if_unbuilt
186 self.rebuild = (self.rebuild_if_new_rev or self.rebuild_if_new_ver or
187 self.rebuild_if_unbuilt)
188
190 parent = dep.collapsed_parent
191 priority = dep.collapsed_priority
192 rebuild_exclude = self._frozen_config.rebuild_exclude
193 rebuild_ignore = self._frozen_config.rebuild_ignore
194 if (self.rebuild and isinstance(parent, Package) and
195 parent.built and priority.buildtime and
196 isinstance(dep_pkg, Package) and
197 not rebuild_exclude.findAtomForPackage(parent) and
198 not rebuild_ignore.findAtomForPackage(dep_pkg)):
199 self._graph.add(dep_pkg, parent, priority)
200
202 """Check whether packages that depend on dep_pkg need to be rebuilt."""
203 dep_root_slot = (dep_pkg.root, dep_pkg.slot_atom)
204 if dep_pkg.built or dep_root_slot in self.orig_rebuild_list:
205 return False
206
207 if self.rebuild_if_unbuilt:
208 # dep_pkg is being installed from source, so binary
209 # packages for parents are invalid. Force rebuild
210 return True
211
212 trees = self._frozen_config.trees
213 vardb = trees[dep_pkg.root]["vartree"].dbapi
214 if self.rebuild_if_new_rev:
215 # Parent packages are valid if a package with the same
216 # cpv is already installed.
217 return dep_pkg.cpv not in vardb.match(dep_pkg.slot_atom)
218
219 # Otherwise, parent packages are valid if a package with the same
220 # version (excluding revision) is already installed.
221 assert self.rebuild_if_new_ver
222 cpv_norev = catpkgsplit(dep_pkg.cpv)[:-1]
223 for inst_cpv in vardb.match(dep_pkg.slot_atom):
224 inst_cpv_norev = catpkgsplit(inst_cpv)[:-1]
225 if inst_cpv_norev == cpv_norev:
226 return False
227
228 return True
229
231 root_slot = (parent.root, parent.slot_atom)
232 if root_slot in self.rebuild_list:
233 return False
234 trees = self._frozen_config.trees
235 reinstall = False
236 for slot_atom, dep_pkg in build_deps.items():
237 dep_root_slot = (dep_pkg.root, slot_atom)
238 if self._needs_rebuild(dep_pkg):
239 self.rebuild_list.add(root_slot)
240 return True
241 elif ("--usepkg" in self._frozen_config.myopts and
242 (dep_root_slot in self.reinstall_list or
243 dep_root_slot in self.rebuild_list or
244 not dep_pkg.installed)):
245
246 # A direct rebuild dependency is being installed. We
247 # should update the parent as well to the latest binary,
248 # if that binary is valid.
249 #
250 # To validate the binary, we check whether all of the
251 # rebuild dependencies are present on the same binhost.
252 #
253 # 1) If parent is present on the binhost, but one of its
254 # rebuild dependencies is not, then the parent should
255 # be rebuilt from source.
256 # 2) Otherwise, the parent binary is assumed to be valid,
257 # because all of its rebuild dependencies are
258 # consistent.
259 bintree = trees[parent.root]["bintree"]
260 uri = bintree.get_pkgindex_uri(parent.cpv)
261 dep_uri = bintree.get_pkgindex_uri(dep_pkg.cpv)
262 bindb = bintree.dbapi
263 if self.rebuild_if_new_ver and uri and uri != dep_uri:
264 cpv_norev = catpkgsplit(dep_pkg.cpv)[:-1]
265 for cpv in bindb.match(dep_pkg.slot_atom):
266 if cpv_norev == catpkgsplit(cpv)[:-1]:
267 dep_uri = bintree.get_pkgindex_uri(cpv)
268 if uri == dep_uri:
269 break
270 if uri and uri != dep_uri:
271 # 1) Remote binary package is invalid because it was
272 # built without dep_pkg. Force rebuild.
273 self.rebuild_list.add(root_slot)
274 return True
275 elif (parent.installed and
276 root_slot not in self.reinstall_list):
277 try:
278 bin_build_time, = bindb.aux_get(parent.cpv,
279 ["BUILD_TIME"])
280 except KeyError:
281 continue
282 if bin_build_time != _unicode(parent.build_time):
283 # 2) Remote binary package is valid, and local package
284 # is not up to date. Force reinstall.
285 reinstall = True
286 if reinstall:
287 self.reinstall_list.add(root_slot)
288 return reinstall
289
291 """
292 Trigger rebuilds where necessary. If pkgA has been updated, and pkgB
293 depends on pkgA at both build-time and run-time, pkgB needs to be
294 rebuilt.
295 """
296 need_restart = False
297 graph = self._graph
298 build_deps = {}
299
300 leaf_nodes = deque(graph.leaf_nodes())
301
302 # Trigger rebuilds bottom-up (starting with the leaves) so that parents
303 # will always know which children are being rebuilt.
304 while graph:
305 if not leaf_nodes:
306 # We'll have to drop an edge. This should be quite rare.
307 leaf_nodes.append(graph.order[-1])
308
309 node = leaf_nodes.popleft()
310 if node not in graph:
311 # This can be triggered by circular dependencies.
312 continue
313 slot_atom = node.slot_atom
314
315 # Remove our leaf node from the graph, keeping track of deps.
316 parents = graph.parent_nodes(node)
317 graph.remove(node)
318 node_build_deps = build_deps.get(node, {})
319 for parent in parents:
320 if parent == node:
321 # Ignore a direct cycle.
322 continue
323 parent_bdeps = build_deps.setdefault(parent, {})
324 parent_bdeps[slot_atom] = node
325 if not graph.child_nodes(parent):
326 leaf_nodes.append(parent)
327
328 # Trigger rebuilds for our leaf node. Because all of our children
329 # have been processed, the build_deps will be completely filled in,
330 # and self.rebuild_list / self.reinstall_list will tell us whether
331 # any of our children need to be rebuilt or reinstalled.
332 if self._trigger_rebuild(node, node_build_deps):
333 need_restart = True
334
335 return need_restart
336
337
339
341 self.myparams = myparams.copy()
342 self._vdb_loaded = False
343 self._allow_backtracking = allow_backtracking
344 # Maps slot atom to package for each Package added to the graph.
345 self._slot_pkg_map = {}
346 # Maps nodes to the reasons they were selected for reinstallation.
347 self._reinstall_nodes = {}
348 self.mydbapi = {}
349 # Contains a filtered view of preferred packages that are selected
350 # from available repositories.
351 self._filtered_trees = {}
352 # Contains installed packages and new packages that have been added
353 # to the graph.
354 self._graph_trees = {}
355 # Caches visible packages returned from _select_package, for use in
356 # depgraph._iter_atoms_for_pkg() SLOT logic.
357 self._visible_pkgs = {}
358 #contains the args created by select_files
359 self._initial_arg_list = []
360 self.digraph = portage.digraph()
361 # manages sets added to the graph
362 self.sets = {}
363 # contains all nodes pulled in by self.sets
364 self._set_nodes = set()
365 # Contains only Blocker -> Uninstall edges
366 self._blocker_uninstalls = digraph()
367 # Contains only Package -> Blocker edges
368 self._blocker_parents = digraph()
369 # Contains only irrelevant Package -> Blocker edges
370 self._irrelevant_blockers = digraph()
371 # Contains only unsolvable Package -> Blocker edges
372 self._unsolvable_blockers = digraph()
373 # Contains all Blocker -> Blocked Package edges
374 self._blocked_pkgs = digraph()
375 # Contains world packages that have been protected from
376 # uninstallation but may not have been added to the graph
377 # if the graph is not complete yet.
378 self._blocked_world_pkgs = {}
379 # Contains packages whose dependencies have been traversed.
380 # This use used to check if we have accounted for blockers
381 # relevant to a package.
382 self._traversed_pkg_deps = set()
383 # This should be ordered such that the backtracker will
384 # attempt to solve conflicts which occurred earlier first,
385 # since an earlier conflict can be the cause of a conflict
386 # which occurs later.
387 self._slot_collision_info = OrderedDict()
388 # Slot collision nodes are not allowed to block other packages since
389 # blocker validation is only able to account for one package per slot.
390 self._slot_collision_nodes = set()
391 self._parent_atoms = {}
392 self._slot_conflict_handler = None
393 self._circular_dependency_handler = None
394 self._serialized_tasks_cache = None
395 self._scheduler_graph = None
396 self._displayed_list = None
397 self._pprovided_args = []
398 self._missing_args = []
399 self._masked_installed = set()
400 self._masked_license_updates = set()
401 self._unsatisfied_deps_for_display = []
402 self._unsatisfied_blockers_for_display = None
403 self._circular_deps_for_display = None
404 self._dep_stack = []
405 self._dep_disjunctive_stack = []
406 self._unsatisfied_deps = []
407 self._initially_unsatisfied_deps = []
408 self._ignored_deps = []
409 self._highest_pkg_cache = {}
410
411 # Binary packages that have been rejected because their USE
412 # didn't match the user's config. It maps packages to a set
413 # of flags causing the rejection.
414 self.ignored_binaries = {}
415
416 self._needed_unstable_keywords = backtrack_parameters.needed_unstable_keywords
417 self._needed_p_mask_changes = backtrack_parameters.needed_p_mask_changes
418 self._needed_license_changes = backtrack_parameters.needed_license_changes
419 self._needed_use_config_changes = backtrack_parameters.needed_use_config_changes
420 self._runtime_pkg_mask = backtrack_parameters.runtime_pkg_mask
421 self._slot_operator_replace_installed = backtrack_parameters.slot_operator_replace_installed
422 self._prune_rebuilds = backtrack_parameters.prune_rebuilds
423 self._need_restart = False
424 # For conditions that always require user intervention, such as
425 # unsatisfied REQUIRED_USE (currently has no autounmask support).
426 self._skip_restart = False
427 self._backtrack_infos = {}
428
429 self._buildpkgonly_deps_unsatisfied = False
430 self._autounmask = depgraph._frozen_config.myopts.get('--autounmask') != 'n'
431 self._success_without_autounmask = False
432 self._traverse_ignored_deps = False
433 self._complete_mode = False
434 self._slot_operator_deps = {}
435
436 for myroot in depgraph._frozen_config.trees:
437 self.sets[myroot] = _depgraph_sets()
438 self._slot_pkg_map[myroot] = {}
439 vardb = depgraph._frozen_config.trees[myroot]["vartree"].dbapi
440 # This dbapi instance will model the state that the vdb will
441 # have after new packages have been installed.
442 fakedb = PackageVirtualDbapi(vardb.settings)
443
444 self.mydbapi[myroot] = fakedb
445 def graph_tree():
446 pass
447 graph_tree.dbapi = fakedb
448 self._graph_trees[myroot] = {}
449 self._filtered_trees[myroot] = {}
450 # Substitute the graph tree for the vartree in dep_check() since we
451 # want atom selections to be consistent with package selections
452 # have already been made.
453 self._graph_trees[myroot]["porttree"] = graph_tree
454 self._graph_trees[myroot]["vartree"] = graph_tree
455 self._graph_trees[myroot]["graph_db"] = graph_tree.dbapi
456 self._graph_trees[myroot]["graph"] = self.digraph
457 def filtered_tree():
458 pass
459 filtered_tree.dbapi = _dep_check_composite_db(depgraph, myroot)
460 self._filtered_trees[myroot]["porttree"] = filtered_tree
461 self._visible_pkgs[myroot] = PackageVirtualDbapi(vardb.settings)
462
463 # Passing in graph_tree as the vartree here could lead to better
464 # atom selections in some cases by causing atoms for packages that
465 # have been added to the graph to be preferred over other choices.
466 # However, it can trigger atom selections that result in
467 # unresolvable direct circular dependencies. For example, this
468 # happens with gwydion-dylan which depends on either itself or
469 # gwydion-dylan-bin. In case gwydion-dylan is not yet installed,
470 # gwydion-dylan-bin needs to be selected in order to avoid a
471 # an unresolvable direct circular dependency.
472 #
473 # To solve the problem described above, pass in "graph_db" so that
474 # packages that have been added to the graph are distinguishable
475 # from other available packages and installed packages. Also, pass
476 # the parent package into self._select_atoms() calls so that
477 # unresolvable direct circular dependencies can be detected and
478 # avoided when possible.
479 self._filtered_trees[myroot]["graph_db"] = graph_tree.dbapi
480 self._filtered_trees[myroot]["graph"] = self.digraph
481 self._filtered_trees[myroot]["vartree"] = \
482 depgraph._frozen_config.trees[myroot]["vartree"]
483
484 dbs = []
485 # (db, pkg_type, built, installed, db_keys)
486 if "remove" in self.myparams:
487 # For removal operations, use _dep_check_composite_db
488 # for availability and visibility checks. This provides
489 # consistency with install operations, so we don't
490 # get install/uninstall cycles like in bug #332719.
491 self._graph_trees[myroot]["porttree"] = filtered_tree
492 else:
493 if "--usepkgonly" not in depgraph._frozen_config.myopts:
494 portdb = depgraph._frozen_config.trees[myroot]["porttree"].dbapi
495 db_keys = list(portdb._aux_cache_keys)
496 dbs.append((portdb, "ebuild", False, False, db_keys))
497
498 if "--usepkg" in depgraph._frozen_config.myopts:
499 bindb = depgraph._frozen_config.trees[myroot]["bintree"].dbapi
500 db_keys = list(bindb._aux_cache_keys)
501 dbs.append((bindb, "binary", True, False, db_keys))
502
503 vardb = depgraph._frozen_config.trees[myroot]["vartree"].dbapi
504 db_keys = list(depgraph._frozen_config._trees_orig[myroot
505 ]["vartree"].dbapi._aux_cache_keys)
506 dbs.append((vardb, "installed", True, True, db_keys))
507 self._filtered_trees[myroot]["dbs"] = dbs
508
510
511 pkg_tree_map = RootConfig.pkg_tree_map
512
513 - def __init__(self, settings, trees, myopts, myparams, spinner,
514 frozen_config=None, backtrack_parameters=BacktrackParameter(), allow_backtracking=False):
515 if frozen_config is None:
516 frozen_config = _frozen_depgraph_config(settings, trees,
517 myopts, spinner)
518 self._frozen_config = frozen_config
519 self._dynamic_config = _dynamic_depgraph_config(self, myparams,
520 allow_backtracking, backtrack_parameters)
521 self._rebuild = _rebuild_config(frozen_config, backtrack_parameters)
522
523 self._select_atoms = self._select_atoms_highest_available
524 self._select_package = self._select_pkg_highest_available
525
526 self._event_loop = (portage._internal_caller and
527 global_event_loop() or EventLoop(main=False))
528
530 """
531 Load installed package metadata if appropriate. This used to be called
532 from the constructor, but that wasn't very nice since this procedure
533 is slow and it generates spinner output. So, now it's called on-demand
534 by various methods when necessary.
535 """
536
537 if self._dynamic_config._vdb_loaded:
538 return
539
540 for myroot in self._frozen_config.trees:
541
542 dynamic_deps = self._dynamic_config.myparams.get(
543 "dynamic_deps", "y") != "n"
544 preload_installed_pkgs = \
545 "--nodeps" not in self._frozen_config.myopts
546
547 fake_vartree = self._frozen_config.trees[myroot]["vartree"]
548 if not fake_vartree.dbapi:
549 # This needs to be called for the first depgraph, but not for
550 # backtracking depgraphs that share the same frozen_config.
551 fake_vartree.sync()
552
553 # FakeVartree.sync() populates virtuals, and we want
554 # self.pkgsettings to have them populated too.
555 self._frozen_config.pkgsettings[myroot] = \
556 portage.config(clone=fake_vartree.settings)
557
558 if preload_installed_pkgs:
559 vardb = fake_vartree.dbapi
560 fakedb = self._dynamic_config._graph_trees[
561 myroot]["vartree"].dbapi
562
563 if not dynamic_deps:
564 for pkg in vardb:
565 fakedb.cpv_inject(pkg)
566 else:
567 max_jobs = self._frozen_config.myopts.get("--jobs")
568 max_load = self._frozen_config.myopts.get("--load-average")
569 scheduler = TaskScheduler(
570 self._dynamic_deps_preload(fake_vartree, fakedb),
571 max_jobs=max_jobs,
572 max_load=max_load,
573 event_loop=fake_vartree._portdb._event_loop)
574 scheduler.start()
575 scheduler.wait()
576
577 self._dynamic_config._vdb_loaded = True
578
580 portdb = fake_vartree._portdb
581 for pkg in fake_vartree.dbapi:
582 self._spinner_update()
583 fakedb.cpv_inject(pkg)
584 ebuild_path, repo_path = \
585 portdb.findname2(pkg.cpv, myrepo=pkg.repo)
586 if ebuild_path is None:
587 fake_vartree.dynamic_deps_preload(pkg, None)
588 continue
589 metadata, ebuild_hash = portdb._pull_valid_cache(
590 pkg.cpv, ebuild_path, repo_path)
591 if metadata is not None:
592 fake_vartree.dynamic_deps_preload(pkg, metadata)
593 else:
594 proc = EbuildMetadataPhase(cpv=pkg.cpv,
595 ebuild_hash=ebuild_hash,
596 portdb=portdb, repo_path=repo_path,
597 settings=portdb.doebuild_settings)
598 proc.addExitListener(
599 self._dynamic_deps_proc_exit(pkg, fake_vartree))
600 yield proc
601
603
604 __slots__ = ('_pkg', '_fake_vartree')
605
609
611 metadata = None
612 if proc.returncode == os.EX_OK:
613 metadata = proc.metadata
614 self._fake_vartree.dynamic_deps_preload(self._pkg, metadata)
615
619
621 """
622 Show binaries that have been ignored because their USE didn't
623 match the user's config.
624 """
625 if not self._dynamic_config.ignored_binaries \
626 or '--quiet' in self._frozen_config.myopts \
627 or self._dynamic_config.myparams.get(
628 "binpkg_respect_use") in ("y", "n"):
629 return
630
631 for pkg in list(self._dynamic_config.ignored_binaries):
632
633 selected_pkg = self._dynamic_config.mydbapi[pkg.root
634 ].match_pkgs(pkg.slot_atom)
635
636 if not selected_pkg:
637 continue
638
639 selected_pkg = selected_pkg[-1]
640 if selected_pkg > pkg:
641 self._dynamic_config.ignored_binaries.pop(pkg)
642 continue
643
644 if selected_pkg.installed and \
645 selected_pkg.cpv == pkg.cpv and \
646 selected_pkg.build_time == pkg.build_time:
647 # We don't care about ignored binaries when an
648 # identical installed instance is selected to
649 # fill the slot.
650 self._dynamic_config.ignored_binaries.pop(pkg)
651 continue
652
653 if not self._dynamic_config.ignored_binaries:
654 return
655
656 self._show_merge_list()
657
658 writemsg("\n!!! The following binary packages have been ignored " + \
659 "due to non matching USE:\n\n", noiselevel=-1)
660
661 for pkg, flags in self._dynamic_config.ignored_binaries.items():
662 flag_display = []
663 for flag in sorted(flags):
664 if flag not in pkg.use.enabled:
665 flag = "-" + flag
666 flag_display.append(flag)
667 flag_display = " ".join(flag_display)
668 # The user can paste this line into package.use
669 writemsg(" =%s %s" % (pkg.cpv, flag_display), noiselevel=-1)
670 if pkg.root_config.settings["ROOT"] != "/":
671 writemsg(" # for %s" % (pkg.root,), noiselevel=-1)
672 writemsg("\n", noiselevel=-1)
673
674 msg = [
675 "",
676 "NOTE: The --binpkg-respect-use=n option will prevent emerge",
677 " from ignoring these binary packages if possible.",
678 " Using --binpkg-respect-use=y will silence this warning."
679 ]
680
681 for line in msg:
682 if line:
683 line = colorize("INFORM", line)
684 writemsg(line + "\n", noiselevel=-1)
685
687
688 # In order to minimize noise, show only the highest
689 # missed update from each SLOT.
690 missed_updates = {}
691 for pkg, mask_reasons in \
692 self._dynamic_config._runtime_pkg_mask.items():
693 if pkg.installed:
694 # Exclude installed here since we only
695 # want to show available updates.
696 continue
697 chosen_pkg = self._dynamic_config.mydbapi[pkg.root
698 ].match_pkgs(pkg.slot_atom)
699 if not chosen_pkg or chosen_pkg[-1] >= pkg:
700 continue
701 k = (pkg.root, pkg.slot_atom)
702 if k in missed_updates:
703 other_pkg, mask_type, parent_atoms = missed_updates[k]
704 if other_pkg > pkg:
705 continue
706 for mask_type, parent_atoms in mask_reasons.items():
707 if not parent_atoms:
708 continue
709 missed_updates[k] = (pkg, mask_type, parent_atoms)
710 break
711
712 return missed_updates
713
715
716 missed_updates = self._get_missed_updates()
717
718 if not missed_updates:
719 return
720
721 missed_update_types = {}
722 for pkg, mask_type, parent_atoms in missed_updates.values():
723 missed_update_types.setdefault(mask_type,
724 []).append((pkg, parent_atoms))
725
726 if '--quiet' in self._frozen_config.myopts and \
727 '--debug' not in self._frozen_config.myopts:
728 missed_update_types.pop("slot conflict", None)
729 missed_update_types.pop("missing dependency", None)
730
731 self._show_missed_update_slot_conflicts(
732 missed_update_types.get("slot conflict"))
733
734 self._show_missed_update_unsatisfied_dep(
735 missed_update_types.get("missing dependency"))
736
738
739 if not missed_updates:
740 return
741
742 self._show_merge_list()
743 backtrack_masked = []
744
745 for pkg, parent_atoms in missed_updates:
746
747 try:
748 for parent, root, atom in parent_atoms:
749 self._show_unsatisfied_dep(root, atom, myparent=parent,
750 check_backtrack=True)
751 except self._backtrack_mask:
752 # This is displayed below in abbreviated form.
753 backtrack_masked.append((pkg, parent_atoms))
754 continue
755
756 writemsg("\n!!! The following update has been skipped " + \
757 "due to unsatisfied dependencies:\n\n", noiselevel=-1)
758
759 writemsg(str(pkg.slot_atom), noiselevel=-1)
760 if pkg.root_config.settings["ROOT"] != "/":
761 writemsg(" for %s" % (pkg.root,), noiselevel=-1)
762 writemsg("\n", noiselevel=-1)
763
764 for parent, root, atom in parent_atoms:
765 self._show_unsatisfied_dep(root, atom, myparent=parent)
766 writemsg("\n", noiselevel=-1)
767
768 if backtrack_masked:
769 # These are shown in abbreviated form, in order to avoid terminal
770 # flooding from mask messages as reported in bug #285832.
771 writemsg("\n!!! The following update(s) have been skipped " + \
772 "due to unsatisfied dependencies\n" + \
773 "!!! triggered by backtracking:\n\n", noiselevel=-1)
774 for pkg, parent_atoms in backtrack_masked:
775 writemsg(str(pkg.slot_atom), noiselevel=-1)
776 if pkg.root_config.settings["ROOT"] != "/":
777 writemsg(" for %s" % (pkg.root,), noiselevel=-1)
778 writemsg("\n", noiselevel=-1)
779
781
782 if not missed_updates:
783 return
784
785 self._show_merge_list()
786 msg = []
787 msg.append("\nWARNING: One or more updates have been " + \
788 "skipped due to a dependency conflict:\n\n")
789
790 indent = " "
791 for pkg, parent_atoms in missed_updates:
792 msg.append(str(pkg.slot_atom))
793 if pkg.root_config.settings["ROOT"] != "/":
794 msg.append(" for %s" % (pkg.root,))
795 msg.append("\n\n")
796
797 for parent, atom in parent_atoms:
798 msg.append(indent)
799 msg.append(str(pkg))
800
801 msg.append(" conflicts with\n")
802 msg.append(2*indent)
803 if isinstance(parent,
804 (PackageArg, AtomArg)):
805 # For PackageArg and AtomArg types, it's
806 # redundant to display the atom attribute.
807 msg.append(str(parent))
808 else:
809 # Display the specific atom from SetArg or
810 # Package types.
811 msg.append("%s required by %s" % (atom, parent))
812 msg.append("\n")
813 msg.append("\n")
814
815 writemsg("".join(msg), noiselevel=-1)
816
818 """Show an informational message advising the user to mask one of the
819 the packages. In some cases it may be possible to resolve this
820 automatically, but support for backtracking (removal nodes that have
821 already been selected) will be required in order to handle all possible
822 cases.
823 """
824
825 if not self._dynamic_config._slot_collision_info:
826 return
827
828 self._show_merge_list()
829
830 self._dynamic_config._slot_conflict_handler = slot_conflict_handler(self)
831 handler = self._dynamic_config._slot_conflict_handler
832
833 conflict = handler.get_conflict()
834 writemsg(conflict, noiselevel=-1)
835
836 explanation = handler.get_explanation()
837 if explanation:
838 writemsg(explanation, noiselevel=-1)
839 return
840
841 if "--quiet" in self._frozen_config.myopts:
842 return
843
844 msg = []
845 msg.append("It may be possible to solve this problem ")
846 msg.append("by using package.mask to prevent one of ")
847 msg.append("those packages from being selected. ")
848 msg.append("However, it is also possible that conflicting ")
849 msg.append("dependencies exist such that they are impossible to ")
850 msg.append("satisfy simultaneously. If such a conflict exists in ")
851 msg.append("the dependencies of two different packages, then those ")
852 msg.append("packages can not be installed simultaneously.")
853 backtrack_opt = self._frozen_config.myopts.get('--backtrack')
854 if not self._dynamic_config._allow_backtracking and \
855 (backtrack_opt is None or \
856 (backtrack_opt > 0 and backtrack_opt < 30)):
857 msg.append(" You may want to try a larger value of the ")
858 msg.append("--backtrack option, such as --backtrack=30, ")
859 msg.append("in order to see if that will solve this conflict ")
860 msg.append("automatically.")
861
862 for line in textwrap.wrap(''.join(msg), 70):
863 writemsg(line + '\n', noiselevel=-1)
864 writemsg('\n', noiselevel=-1)
865
866 msg = []
867 msg.append("For more information, see MASKED PACKAGES ")
868 msg.append("section in the emerge man page or refer ")
869 msg.append("to the Gentoo Handbook.")
870 for line in textwrap.wrap(''.join(msg), 70):
871 writemsg(line + '\n', noiselevel=-1)
872 writemsg('\n', noiselevel=-1)
873
875 """
876 If there are any slot conflicts and backtracking is enabled,
877 _complete_graph should complete the graph before this method
878 is called, so that all relevant reverse dependencies are
879 available for use in backtracking decisions.
880 """
881 for (slot_atom, root), slot_nodes in \
882 self._dynamic_config._slot_collision_info.items():
883 self._process_slot_conflict(root, slot_atom, slot_nodes)
884
886 """
887 Process slot conflict data to identify specific atoms which
888 lead to conflict. These atoms only match a subset of the
889 packages that have been pulled into a given slot.
890 """
891
892 debug = "--debug" in self._frozen_config.myopts
893
894 slot_parent_atoms = set()
895 for pkg in slot_nodes:
896 parent_atoms = self._dynamic_config._parent_atoms.get(pkg)
897 if not parent_atoms:
898 continue
899 slot_parent_atoms.update(parent_atoms)
900
901 conflict_pkgs = []
902 conflict_atoms = {}
903 for pkg in slot_nodes:
904
905 if self._dynamic_config._allow_backtracking and \
906 pkg in self._dynamic_config._runtime_pkg_mask:
907 if debug:
908 writemsg_level(
909 "!!! backtracking loop detected: %s %s\n" % \
910 (pkg,
911 self._dynamic_config._runtime_pkg_mask[pkg]),
912 level=logging.DEBUG, noiselevel=-1)
913
914 parent_atoms = self._dynamic_config._parent_atoms.get(pkg)
915 if parent_atoms is None:
916 parent_atoms = set()
917 self._dynamic_config._parent_atoms[pkg] = parent_atoms
918
919 all_match = True
920 for parent_atom in slot_parent_atoms:
921 if parent_atom in parent_atoms:
922 continue
923 # Use package set for matching since it will match via
924 # PROVIDE when necessary, while match_from_list does not.
925 parent, atom = parent_atom
926 atom_set = InternalPackageSet(
927 initial_atoms=(atom,), allow_repo=True)
928 if atom_set.findAtomForPackage(pkg,
929 modified_use=self._pkg_use_enabled(pkg)):
930 parent_atoms.add(parent_atom)
931 else:
932 all_match = False
933 conflict_atoms.setdefault(parent_atom, set()).add(pkg)
934
935 if not all_match:
936 conflict_pkgs.append(pkg)
937
938 if conflict_pkgs and \
939 self._dynamic_config._allow_backtracking and \
940 not self._accept_blocker_conflicts():
941 remaining = []
942 for pkg in conflict_pkgs:
943 if self._slot_conflict_backtrack_abi(pkg,
944 slot_nodes, conflict_atoms):
945 backtrack_infos = self._dynamic_config._backtrack_infos
946 config = backtrack_infos.setdefault("config", {})
947 config.setdefault("slot_conflict_abi", set()).add(pkg)
948 else:
949 remaining.append(pkg)
950 if remaining:
951 self._slot_confict_backtrack(root, slot_atom,
952 slot_parent_atoms, remaining)
953
956
957 debug = "--debug" in self._frozen_config.myopts
958 existing_node = self._dynamic_config._slot_pkg_map[root][slot_atom]
959 backtrack_data = []
960 # The ordering of backtrack_data can make
961 # a difference here, because both mask actions may lead
962 # to valid, but different, solutions and the one with
963 # 'existing_node' masked is usually the better one. Because
964 # of that, we choose an order such that
965 # the backtracker will first explore the choice with
966 # existing_node masked. The backtracker reverses the
967 # order, so the order it uses is the reverse of the
968 # order shown here. See bug #339606.
969 if existing_node in conflict_pkgs and \
970 existing_node is not conflict_pkgs[-1]:
971 conflict_pkgs.remove(existing_node)
972 conflict_pkgs.append(existing_node)
973 for to_be_masked in conflict_pkgs:
974 # For missed update messages, find out which
975 # atoms matched to_be_selected that did not
976 # match to_be_masked.
977 parent_atoms = \
978 self._dynamic_config._parent_atoms.get(to_be_masked, set())
979 conflict_atoms = set(parent_atom for parent_atom in all_parents \
980 if parent_atom not in parent_atoms)
981 backtrack_data.append((to_be_masked, conflict_atoms))
982
983 if len(backtrack_data) > 1:
984 # NOTE: Generally, we prefer to mask the higher
985 # version since this solves common cases in which a
986 # lower version is needed so that all dependencies
987 # will be satisfied (bug #337178). However, if
988 # existing_node happens to be installed then we
989 # mask that since this is a common case that is
990 # triggered when --update is not enabled.
991 if existing_node.installed:
992 pass
993 elif any(pkg > existing_node for pkg in conflict_pkgs):
994 backtrack_data.reverse()
995
996 to_be_masked = backtrack_data[-1][0]
997
998 self._dynamic_config._backtrack_infos.setdefault(
999 "slot conflict", []).append(backtrack_data)
1000 self._dynamic_config._need_restart = True
1001 if debug:
1002 msg = []
1003 msg.append("")
1004 msg.append("")
1005 msg.append("backtracking due to slot conflict:")
1006 msg.append(" first package: %s" % existing_node)
1007 msg.append(" package to mask: %s" % to_be_masked)
1008 msg.append(" slot: %s" % slot_atom)
1009 msg.append(" parents: %s" % ", ".join( \
1010 "(%s, '%s')" % (ppkg, atom) for ppkg, atom in all_parents))
1011 msg.append("")
1012 writemsg_level("".join("%s\n" % l for l in msg),
1013 noiselevel=-1, level=logging.DEBUG)
1014
1016 """
1017 If one or more conflict atoms have a slot/sub-slot dep that can be resolved
1018 by rebuilding the parent package, then schedule the rebuild via
1019 backtracking, and return True. Otherwise, return False.
1020 """
1021
1022 found_update = False
1023 for parent_atom, conflict_pkgs in conflict_atoms.items():
1024 parent, atom = parent_atom
1025 if atom.slot_operator != "=" or not parent.built:
1026 continue
1027
1028 if pkg not in conflict_pkgs:
1029 continue
1030
1031 for other_pkg in slot_nodes:
1032 if other_pkg in conflict_pkgs:
1033 continue
1034
1035 dep = Dependency(atom=atom, child=other_pkg,
1036 parent=parent, root=pkg.root)
1037
1038 new_dep = \
1039 self._slot_operator_update_probe_slot_conflict(dep)
1040 if new_dep is not None:
1041 self._slot_operator_update_backtrack(dep,
1042 new_dep=new_dep)
1043 found_update = True
1044
1045 return found_update
1046
1048 """
1049 @rtype: bool
1050 @return: True if dep.child should be rebuilt due to a change
1051 in sub-slot (without revbump, as in bug #456208).
1052 """
1053 if not (isinstance(dep.parent, Package) and \
1054 not dep.parent.built and dep.child.built):
1055 return None
1056
1057 root_config = self._frozen_config.roots[dep.root]
1058 matches = []
1059 try:
1060 matches.append(self._pkg(dep.child.cpv, "ebuild",
1061 root_config, myrepo=dep.child.repo))
1062 except PackageNotFound:
1063 pass
1064
1065 for unbuilt_child in chain(matches,
1066 self._iter_match_pkgs(root_config, "ebuild",
1067 Atom("=%s" % (dep.child.cpv,)))):
1068 if unbuilt_child in self._dynamic_config._runtime_pkg_mask:
1069 continue
1070 if self._frozen_config.excluded_pkgs.findAtomForPackage(
1071 unbuilt_child,
1072 modified_use=self._pkg_use_enabled(unbuilt_child)):
1073 continue
1074 if not self._pkg_visibility_check(unbuilt_child):
1075 continue
1076 break
1077 else:
1078 return None
1079
1080 if unbuilt_child.slot == dep.child.slot and \
1081 unbuilt_child.sub_slot == dep.child.sub_slot:
1082 return None
1083
1084 return unbuilt_child
1085
1087 child = dep.child
1088 if "--debug" in self._frozen_config.myopts:
1089 msg = []
1090 msg.append("")
1091 msg.append("")
1092 msg.append("backtracking due to slot/sub-slot change:")
1093 msg.append(" child package: %s" % child)
1094 msg.append(" child slot: %s/%s" %
1095 (child.slot, child.sub_slot))
1096 msg.append(" new child: %s" % new_child_slot)
1097 msg.append(" new child slot: %s/%s" %
1098 (new_child_slot.slot, new_child_slot.sub_slot))
1099 msg.append(" parent package: %s" % dep.parent)
1100 msg.append(" atom: %s" % dep.atom)
1101 msg.append("")
1102 writemsg_level("\n".join(msg),
1103 noiselevel=-1, level=logging.DEBUG)
1104 backtrack_infos = self._dynamic_config._backtrack_infos
1105 config = backtrack_infos.setdefault("config", {})
1106
1107 # mask unwanted binary packages if necessary
1108 masks = {}
1109 if not child.installed:
1110 masks.setdefault(dep.child, {})["slot_operator_mask_built"] = None
1111 if masks:
1112 config.setdefault("slot_operator_mask_built", {}).update(masks)
1113
1114 # trigger replacement of installed packages if necessary
1115 reinstalls = set()
1116 if child.installed:
1117 replacement_atom = self._replace_installed_atom(child)
1118 if replacement_atom is not None:
1119 reinstalls.add((child.root, replacement_atom))
1120 if reinstalls:
1121 config.setdefault("slot_operator_replace_installed",
1122 set()).update(reinstalls)
1123
1124 self._dynamic_config._need_restart = True
1125
1128 if new_child_slot is None:
1129 child = dep.child
1130 else:
1131 child = new_child_slot
1132 if "--debug" in self._frozen_config.myopts:
1133 msg = []
1134 msg.append("")
1135 msg.append("")
1136 msg.append("backtracking due to missed slot abi update:")
1137 msg.append(" child package: %s" % child)
1138 if new_child_slot is not None:
1139 msg.append(" new child slot package: %s" % new_child_slot)
1140 msg.append(" parent package: %s" % dep.parent)
1141 if new_dep is not None:
1142 msg.append(" new parent pkg: %s" % new_dep.parent)
1143 msg.append(" atom: %s" % dep.atom)
1144 msg.append("")
1145 writemsg_level("\n".join(msg),
1146 noiselevel=-1, level=logging.DEBUG)
1147 backtrack_infos = self._dynamic_config._backtrack_infos
1148 config = backtrack_infos.setdefault("config", {})
1149
1150 # mask unwanted binary packages if necessary
1151 abi_masks = {}
1152 if new_child_slot is None:
1153 if not child.installed:
1154 abi_masks.setdefault(child, {})["slot_operator_mask_built"] = None
1155 if not dep.parent.installed:
1156 abi_masks.setdefault(dep.parent, {})["slot_operator_mask_built"] = None
1157 if abi_masks:
1158 config.setdefault("slot_operator_mask_built", {}).update(abi_masks)
1159
1160 # trigger replacement of installed packages if necessary
1161 abi_reinstalls = set()
1162 if dep.parent.installed:
1163 if new_dep is not None:
1164 replacement_atom = new_dep.parent.slot_atom
1165 else:
1166 replacement_atom = self._replace_installed_atom(dep.parent)
1167 if replacement_atom is not None:
1168 abi_reinstalls.add((dep.parent.root, replacement_atom))
1169 if new_child_slot is None and child.installed:
1170 replacement_atom = self._replace_installed_atom(child)
1171 if replacement_atom is not None:
1172 abi_reinstalls.add((child.root, replacement_atom))
1173 if abi_reinstalls:
1174 config.setdefault("slot_operator_replace_installed",
1175 set()).update(abi_reinstalls)
1176
1177 self._dynamic_config._need_restart = True
1178
1180 new_dep = self._slot_operator_update_probe(dep, slot_conflict=True)
1181
1182 if new_dep is not None:
1183 return new_dep
1184
1185 if self._dynamic_config._autounmask is True:
1186
1187 for autounmask_level in self._autounmask_levels():
1188
1189 new_dep = self._slot_operator_update_probe(dep,
1190 slot_conflict=True, autounmask_level=autounmask_level)
1191
1192 if new_dep is not None:
1193 return new_dep
1194
1195 return None
1196
1197 - def _slot_operator_update_probe(self, dep, new_child_slot=False,
1198 slot_conflict=False, autounmask_level=None):
1199 """
1200 slot/sub-slot := operators tend to prevent updates from getting pulled in,
1201 since installed packages pull in packages with the slot/sub-slot that they
1202 were built against. Detect this case so that we can schedule rebuilds
1203 and reinstalls when appropriate.
1204 NOTE: This function only searches for updates that involve upgrades
1205 to higher versions, since the logic required to detect when a
1206 downgrade would be desirable is not implemented.
1207 """
1208
1209 if dep.child.installed and \
1210 self._frozen_config.excluded_pkgs.findAtomForPackage(dep.child,
1211 modified_use=self._pkg_use_enabled(dep.child)):
1212 return None
1213
1214 if dep.parent.installed and \
1215 self._frozen_config.excluded_pkgs.findAtomForPackage(dep.parent,
1216 modified_use=self._pkg_use_enabled(dep.parent)):
1217 return None
1218
1219 debug = "--debug" in self._frozen_config.myopts
1220 selective = "selective" in self._dynamic_config.myparams
1221 want_downgrade = None
1222
1223 for replacement_parent in self._iter_similar_available(dep.parent,
1224 dep.parent.slot_atom, autounmask_level=autounmask_level):
1225
1226 selected_atoms = None
1227
1228 for atom in replacement_parent.validated_atoms:
1229 if not atom.slot_operator == "=" or \
1230 atom.blocker or \
1231 atom.cp != dep.atom.cp:
1232 continue
1233
1234 # Discard USE deps, we're only searching for an approximate
1235 # pattern, and dealing with USE states is too complex for
1236 # this purpose.
1237 unevaluated_atom = atom.unevaluated_atom
1238 atom = atom.without_use
1239
1240 if replacement_parent.built and \
1241 portage.dep._match_slot(atom, dep.child):
1242 # Our selected replacement_parent appears to be built
1243 # for the existing child selection. So, discard this
1244 # parent and search for another.
1245 break
1246
1247 for pkg in self._iter_similar_available(
1248 dep.child, atom):
1249 if pkg.slot == dep.child.slot and \
1250 pkg.sub_slot == dep.child.sub_slot:
1251 # If slot/sub-slot is identical, then there's
1252 # no point in updating.
1253 continue
1254 if new_child_slot:
1255 if pkg.slot == dep.child.slot:
1256 continue
1257 if pkg < dep.child:
1258 # the new slot only matters if the
1259 # package version is higher
1260 continue
1261 else:
1262 if pkg.slot != dep.child.slot:
1263 continue
1264 if pkg < dep.child:
1265 if want_downgrade is None:
1266 want_downgrade = self._downgrade_probe(dep.child)
1267 # be careful not to trigger a rebuild when
1268 # the only version available with a
1269 # different slot_operator is an older version
1270 if not want_downgrade:
1271 continue
1272
1273 insignificant = False
1274 if not slot_conflict and \
1275 selective and \
1276 dep.parent.installed and \
1277 dep.child.installed and \
1278 dep.parent.cpv == replacement_parent.cpv and \
1279 dep.child.cpv == pkg.cpv:
1280 # Then can happen if the child's sub-slot changed
1281 # without a revision bump. The sub-slot change is
1282 # considered insignificant until one of its parent
1283 # packages needs to be rebuilt (which may trigger a
1284 # slot conflict).
1285 insignificant = True
1286
1287 if not insignificant:
1288 # Evaluate USE conditionals and || deps, in order
1289 # to see if this atom is really desirable, since
1290 # otherwise we may trigger an undesirable rebuild
1291 # as in bug #460304.
1292 if selected_atoms is None:
1293 selected_atoms = self._select_atoms_probe(
1294 dep.child.root, replacement_parent)
1295 if unevaluated_atom not in selected_atoms:
1296 continue
1297
1298 if debug:
1299 msg = []
1300 msg.append("")
1301 msg.append("")
1302 msg.append("slot_operator_update_probe:")
1303 msg.append(" existing child package: %s" % dep.child)
1304 msg.append(" existing parent package: %s" % dep.parent)
1305 msg.append(" new child package: %s" % pkg)
1306 msg.append(" new parent package: %s" % replacement_parent)
1307 if insignificant:
1308 msg.append("insignificant changes detected")
1309 msg.append("")
1310 writemsg_level("\n".join(msg),
1311 noiselevel=-1, level=logging.DEBUG)
1312
1313 if insignificant:
1314 return None
1315
1316 return Dependency(parent=replacement_parent,
1317 child=pkg, atom=unevaluated_atom)
1318
1319 if debug:
1320 msg = []
1321 msg.append("")
1322 msg.append("")
1323 msg.append("slot_operator_update_probe:")
1324 msg.append(" existing child package: %s" % dep.child)
1325 msg.append(" existing parent package: %s" % dep.parent)
1326 msg.append(" new child package: %s" % None)
1327 msg.append(" new parent package: %s" % None)
1328 msg.append("")
1329 writemsg_level("\n".join(msg),
1330 noiselevel=-1, level=logging.DEBUG)
1331
1332 return None
1333
1335
1336 if dep.parent.installed and \
1337 self._frozen_config.excluded_pkgs.findAtomForPackage(dep.parent,
1338 modified_use=self._pkg_use_enabled(dep.parent)):
1339 return False
1340
1341 debug = "--debug" in self._frozen_config.myopts
1342
1343 for replacement_parent in self._iter_similar_available(dep.parent,
1344 dep.parent.slot_atom):
1345
1346 for atom in replacement_parent.validated_atoms:
1347 if not atom.slot_operator == "=" or \
1348 atom.blocker or \
1349 atom.cp != dep.atom.cp:
1350 continue
1351
1352 # Discard USE deps, we're only searching for an approximate
1353 # pattern, and dealing with USE states is too complex for
1354 # this purpose.
1355 atom = atom.without_use
1356
1357 pkg, existing_node = self._select_package(dep.root, atom,
1358 onlydeps=dep.onlydeps)
1359
1360 if pkg is not None:
1361
1362 if debug:
1363 msg = []
1364 msg.append("")
1365 msg.append("")
1366 msg.append("slot_operator_unsatisfied_probe:")
1367 msg.append(" existing parent package: %s" % dep.parent)
1368 msg.append(" existing parent atom: %s" % dep.atom)
1369 msg.append(" new parent package: %s" % replacement_parent)
1370 msg.append(" new child package: %s" % pkg)
1371 msg.append("")
1372 writemsg_level("\n".join(msg),
1373 noiselevel=-1, level=logging.DEBUG)
1374
1375 return True
1376
1377 if debug:
1378 msg = []
1379 msg.append("")
1380 msg.append("")
1381 msg.append("slot_operator_unsatisfied_probe:")
1382 msg.append(" existing parent package: %s" % dep.parent)
1383 msg.append(" existing parent atom: %s" % dep.atom)
1384 msg.append(" new parent package: %s" % None)
1385 msg.append(" new child package: %s" % None)
1386 msg.append("")
1387 writemsg_level("\n".join(msg),
1388 noiselevel=-1, level=logging.DEBUG)
1389
1390 return False
1391
1393
1394 parent = dep.parent
1395
1396 if "--debug" in self._frozen_config.myopts:
1397 msg = []
1398 msg.append("")
1399 msg.append("")
1400 msg.append("backtracking due to unsatisfied "
1401 "built slot-operator dep:")
1402 msg.append(" parent package: %s" % parent)
1403 msg.append(" atom: %s" % dep.atom)
1404 msg.append("")
1405 writemsg_level("\n".join(msg),
1406 noiselevel=-1, level=logging.DEBUG)
1407
1408 backtrack_infos = self._dynamic_config._backtrack_infos
1409 config = backtrack_infos.setdefault("config", {})
1410
1411 # mask unwanted binary packages if necessary
1412 masks = {}
1413 if not parent.installed:
1414 masks.setdefault(parent, {})["slot_operator_mask_built"] = None
1415 if masks:
1416 config.setdefault("slot_operator_mask_built", {}).update(masks)
1417
1418 # trigger replacement of installed packages if necessary
1419 reinstalls = set()
1420 if parent.installed:
1421 replacement_atom = self._replace_installed_atom(parent)
1422 if replacement_atom is not None:
1423 reinstalls.add((parent.root, replacement_atom))
1424 if reinstalls:
1425 config.setdefault("slot_operator_replace_installed",
1426 set()).update(reinstalls)
1427
1428 self._dynamic_config._need_restart = True
1429
1431 """
1432 Detect cases where a downgrade of the given package is considered
1433 desirable due to the current version being masked or unavailable.
1434 """
1435 available_pkg = None
1436 for available_pkg in self._iter_similar_available(pkg,
1437 pkg.slot_atom):
1438 if available_pkg >= pkg:
1439 # There's an available package of the same or higher
1440 # version, so downgrade seems undesirable.
1441 return False
1442
1443 return available_pkg is not None
1444
1446 selected_atoms = []
1447 use = self._pkg_use_enabled(pkg)
1448 for k in pkg._dep_keys:
1449 v = pkg._metadata.get(k)
1450 if not v:
1451 continue
1452 selected_atoms.extend(self._select_atoms(
1453 root, v, myuse=use, parent=pkg)[pkg])
1454 return frozenset(x.unevaluated_atom for
1455 x in selected_atoms)
1456
1458 """
1459 Given a package that's in the graph, do a rough check to
1460 see if a similar package is available to install. The given
1461 graph_pkg itself may be yielded only if it's not installed.
1462 """
1463
1464 usepkgonly = "--usepkgonly" in self._frozen_config.myopts
1465 useoldpkg_atoms = self._frozen_config.useoldpkg_atoms
1466 use_ebuild_visibility = self._frozen_config.myopts.get(
1467 '--use-ebuild-visibility', 'n') != 'n'
1468
1469 for pkg in self._iter_match_pkgs_any(
1470 graph_pkg.root_config, atom):
1471 if pkg.cp != graph_pkg.cp:
1472 # discard old-style virtual match
1473 continue
1474 if pkg.installed:
1475 continue
1476 if pkg in self._dynamic_config._runtime_pkg_mask:
1477 continue
1478 if self._frozen_config.excluded_pkgs.findAtomForPackage(pkg,
1479 modified_use=self._pkg_use_enabled(pkg)):
1480 continue
1481 if pkg.built:
1482 if self._equiv_binary_installed(pkg):
1483 continue
1484 if not (not use_ebuild_visibility and
1485 (usepkgonly or useoldpkg_atoms.findAtomForPackage(
1486 pkg, modified_use=self._pkg_use_enabled(pkg)))) and \
1487 not self._equiv_ebuild_visible(pkg,
1488 autounmask_level=autounmask_level):
1489 continue
1490 if not self._pkg_visibility_check(pkg,
1491 autounmask_level=autounmask_level):
1492 continue
1493 yield pkg
1494
1496 """
1497 Given an installed package, generate an atom suitable for
1498 slot_operator_replace_installed backtracking info. The replacement
1499 SLOT may differ from the installed SLOT, so first search by cpv.
1500 """
1501 built_pkgs = []
1502 for pkg in self._iter_similar_available(inst_pkg,
1503 Atom("=%s" % inst_pkg.cpv)):
1504 if not pkg.built:
1505 return pkg.slot_atom
1506 elif not pkg.installed:
1507 # avoid using SLOT from a built instance
1508 built_pkgs.append(pkg)
1509
1510 for pkg in self._iter_similar_available(inst_pkg, inst_pkg.slot_atom):
1511 if not pkg.built:
1512 return pkg.slot_atom
1513 elif not pkg.installed:
1514 # avoid using SLOT from a built instance
1515 built_pkgs.append(pkg)
1516
1517 if built_pkgs:
1518 best_version = None
1519 for pkg in built_pkgs:
1520 if best_version is None or pkg > best_version:
1521 best_version = pkg
1522 return best_version.slot_atom
1523
1524 return None
1525
1527 """
1528 Search for packages with slot-operator deps on older slots, and schedule
1529 rebuilds if they can link to a newer slot that's in the graph.
1530 """
1531
1532 rebuild_if_new_slot = self._dynamic_config.myparams.get(
1533 "rebuild_if_new_slot", "y") == "y"
1534
1535 for slot_key, slot_info in self._dynamic_config._slot_operator_deps.items():
1536
1537 for dep in slot_info:
1538
1539 atom = dep.atom
1540 if atom.slot_operator is None:
1541 continue
1542
1543 if not atom.slot_operator_built:
1544 new_child_slot = self._slot_change_probe(dep)
1545 if new_child_slot is not None:
1546 self._slot_change_backtrack(dep, new_child_slot)
1547 continue
1548
1549 if not (dep.parent and
1550 isinstance(dep.parent, Package) and dep.parent.built):
1551 continue
1552
1553 # Check for slot update first, since we don't want to
1554 # trigger reinstall of the child package when a newer
1555 # slot will be used instead.
1556 if rebuild_if_new_slot:
1557 new_dep = self._slot_operator_update_probe(dep,
1558 new_child_slot=True)
1559 if new_dep is not None:
1560 self._slot_operator_update_backtrack(dep,
1561 new_child_slot=new_dep.child)
1562 break
1563
1564 if dep.want_update:
1565 if self._slot_operator_update_probe(dep):
1566 self._slot_operator_update_backtrack(dep)
1567 break
1568
1569 - def _reinstall_for_flags(self, pkg, forced_flags,
1570 orig_use, orig_iuse, cur_use, cur_iuse):
1571 """Return a set of flags that trigger reinstallation, or None if there
1572 are no such flags."""
1573
1574 # binpkg_respect_use: Behave like newuse by default. If newuse is
1575 # False and changed_use is True, then behave like changed_use.
1576 binpkg_respect_use = (pkg.built and
1577 self._dynamic_config.myparams.get("binpkg_respect_use")
1578 in ("y", "auto"))
1579 newuse = "--newuse" in self._frozen_config.myopts
1580 changed_use = "changed-use" == self._frozen_config.myopts.get("--reinstall")
1581 feature_flags = _get_feature_flags(
1582 _get_eapi_attrs(pkg.eapi))
1583
1584 if newuse or (binpkg_respect_use and not changed_use):
1585 flags = set(orig_iuse.symmetric_difference(
1586 cur_iuse).difference(forced_flags))
1587 flags.update(orig_iuse.intersection(orig_use).symmetric_difference(
1588 cur_iuse.intersection(cur_use)))
1589 flags.difference_update(feature_flags)
1590 if flags:
1591 return flags
1592
1593 elif changed_use or binpkg_respect_use:
1594 flags = set(orig_iuse.intersection(orig_use).symmetric_difference(
1595 cur_iuse.intersection(cur_use)))
1596 flags.difference_update(feature_flags)
1597 if flags:
1598 return flags
1599 return None
1600
1602 dep_stack = self._dynamic_config._dep_stack
1603 dep_disjunctive_stack = self._dynamic_config._dep_disjunctive_stack
1604 while dep_stack or dep_disjunctive_stack:
1605 self._spinner_update()
1606 while dep_stack:
1607 dep = dep_stack.pop()
1608 if isinstance(dep, Package):
1609 if not self._add_pkg_deps(dep,
1610 allow_unsatisfied=allow_unsatisfied):
1611 return 0
1612 continue
1613 if not self._add_dep(dep, allow_unsatisfied=allow_unsatisfied):
1614 return 0
1615 if dep_disjunctive_stack:
1616 if not self._pop_disjunction(allow_unsatisfied):
1617 return 0
1618 return 1
1619
1621 """
1622 Iterate over a list of DependencyArg instances and yield all
1623 instances given in the input together with additional SetArg
1624 instances that are generated from nested sets.
1625 @param input_args: An iterable of DependencyArg instances
1626 @type input_args: Iterable
1627 @param add_to_digraph: If True then add SetArg instances
1628 to the digraph, in order to record parent -> child
1629 relationships from nested sets
1630 @type add_to_digraph: Boolean
1631 @rtype: Iterable
1632 @return: All args given in the input together with additional
1633 SetArg instances that are generated from nested sets
1634 """
1635
1636 traversed_set_args = set()
1637
1638 for arg in input_args:
1639 if not isinstance(arg, SetArg):
1640 yield arg
1641 continue
1642
1643 root_config = arg.root_config
1644 depgraph_sets = self._dynamic_config.sets[root_config.root]
1645 arg_stack = [arg]
1646 while arg_stack:
1647 arg = arg_stack.pop()
1648 if arg in traversed_set_args:
1649 continue
1650 traversed_set_args.add(arg)
1651
1652 if add_to_digraph:
1653 self._dynamic_config.digraph.add(arg, None,
1654 priority=BlockerDepPriority.instance)
1655
1656 yield arg
1657
1658 # Traverse nested sets and add them to the stack
1659 # if they're not already in the graph. Also, graph
1660 # edges between parent and nested sets.
1661 for token in arg.pset.getNonAtoms():
1662 if not token.startswith(SETPREFIX):
1663 continue
1664 s = token[len(SETPREFIX):]
1665 nested_set = depgraph_sets.sets.get(s)
1666 if nested_set is None:
1667 nested_set = root_config.sets.get(s)
1668 if nested_set is not None:
1669 nested_arg = SetArg(arg=token, pset=nested_set,
1670 root_config=root_config)
1671 arg_stack.append(nested_arg)
1672 if add_to_digraph:
1673 self._dynamic_config.digraph.add(nested_arg, arg,
1674 priority=BlockerDepPriority.instance)
1675 depgraph_sets.sets[nested_arg.name] = nested_arg.pset
1676
1678 debug = "--debug" in self._frozen_config.myopts
1679 buildpkgonly = "--buildpkgonly" in self._frozen_config.myopts
1680 nodeps = "--nodeps" in self._frozen_config.myopts
1681 if dep.blocker:
1682 if not buildpkgonly and \
1683 not nodeps and \
1684 not dep.collapsed_priority.ignored and \
1685 not dep.collapsed_priority.optional and \
1686 dep.parent not in self._dynamic_config._slot_collision_nodes:
1687 if dep.parent.onlydeps:
1688 # It's safe to ignore blockers if the
1689 # parent is an --onlydeps node.
1690 return 1
1691 # The blocker applies to the root where
1692 # the parent is or will be installed.
1693 blocker = Blocker(atom=dep.atom,
1694 eapi=dep.parent.eapi,
1695 priority=dep.priority, root=dep.parent.root)
1696 self._dynamic_config._blocker_parents.add(blocker, dep.parent)
1697 return 1
1698
1699 if dep.child is None:
1700 dep_pkg, existing_node = self._select_package(dep.root, dep.atom,
1701 onlydeps=dep.onlydeps)
1702 else:
1703 # The caller has selected a specific package
1704 # via self._minimize_packages().
1705 dep_pkg = dep.child
1706 existing_node = self._dynamic_config._slot_pkg_map[
1707 dep.root].get(dep_pkg.slot_atom)
1708
1709 if not dep_pkg:
1710 if (dep.collapsed_priority.optional or
1711 dep.collapsed_priority.ignored):
1712 # This is an unnecessary build-time dep.
1713 return 1
1714 if allow_unsatisfied:
1715 self._dynamic_config._unsatisfied_deps.append(dep)
1716 return 1
1717 self._dynamic_config._unsatisfied_deps_for_display.append(
1718 ((dep.root, dep.atom), {"myparent":dep.parent}))
1719
1720 # The parent node should not already be in
1721 # runtime_pkg_mask, since that would trigger an
1722 # infinite backtracking loop.
1723 if self._dynamic_config._allow_backtracking:
1724 if dep.parent in self._dynamic_config._runtime_pkg_mask:
1725 if debug:
1726 writemsg(
1727 "!!! backtracking loop detected: %s %s\n" % \
1728 (dep.parent,
1729 self._dynamic_config._runtime_pkg_mask[
1730 dep.parent]), noiselevel=-1)
1731 elif dep.atom.slot_operator_built and \
1732 self._slot_operator_unsatisfied_probe(dep):
1733 self._slot_operator_unsatisfied_backtrack(dep)
1734 return 1
1735 else:
1736 # Do not backtrack if only USE have to be changed in
1737 # order to satisfy the dependency. Note that when
1738 # want_restart_for_use_change sets the need_restart
1739 # flag, it causes _select_pkg_highest_available to
1740 # return None, and eventually we come through here
1741 # and skip the "missing dependency" backtracking path.
1742 dep_pkg, existing_node = \
1743 self._select_package(dep.root, dep.atom.without_use,
1744 onlydeps=dep.onlydeps)
1745 if dep_pkg is None:
1746 self._dynamic_config._backtrack_infos["missing dependency"] = dep
1747 self._dynamic_config._need_restart = True
1748 if debug:
1749 msg = []
1750 msg.append("")
1751 msg.append("")
1752 msg.append("backtracking due to unsatisfied dep:")
1753 msg.append(" parent: %s" % dep.parent)
1754 msg.append(" priority: %s" % dep.priority)
1755 msg.append(" root: %s" % dep.root)
1756 msg.append(" atom: %s" % dep.atom)
1757 msg.append("")
1758 writemsg_level("".join("%s\n" % l for l in msg),
1759 noiselevel=-1, level=logging.DEBUG)
1760
1761 return 0
1762
1763 self._rebuild.add(dep_pkg, dep)
1764
1765 ignore = dep.collapsed_priority.ignored and \
1766 not self._dynamic_config._traverse_ignored_deps
1767 if not ignore and not self._add_pkg(dep_pkg, dep):
1768 return 0
1769 return 1
1770
1772 existing_node = self._dynamic_config._slot_pkg_map[pkg.root].get(pkg.slot_atom)
1773 matches = None
1774 if existing_node:
1775 matches = pkg.cpv == existing_node.cpv
1776 if pkg != existing_node and \
1777 atom is not None:
1778 # Use package set for matching since it will match via
1779 # PROVIDE when necessary, while match_from_list does not.
1780 matches = bool(InternalPackageSet(initial_atoms=(atom,),
1781 allow_repo=True).findAtomForPackage(existing_node,
1782 modified_use=self._pkg_use_enabled(existing_node)))
1783
1784 return (existing_node, matches)
1785
1787 """
1788 Adds a package to the depgraph, queues dependencies, and handles
1789 slot conflicts.
1790 """
1791 debug = "--debug" in self._frozen_config.myopts
1792 myparent = None
1793 priority = None
1794 depth = 0
1795 if dep is None:
1796 dep = Dependency()
1797 else:
1798 myparent = dep.parent
1799 priority = dep.priority
1800 depth = dep.depth
1801 if priority is None:
1802 priority = DepPriority()
1803
1804 if debug:
1805 writemsg_level(
1806 "\n%s%s %s\n" % ("Child:".ljust(15), pkg,
1807 pkg_use_display(pkg, self._frozen_config.myopts,
1808 modified_use=self._pkg_use_enabled(pkg))),
1809 level=logging.DEBUG, noiselevel=-1)
1810 if isinstance(myparent,
1811 (PackageArg, AtomArg)):
1812 # For PackageArg and AtomArg types, it's
1813 # redundant to display the atom attribute.
1814 writemsg_level(
1815 "%s%s\n" % ("Parent Dep:".ljust(15), myparent),
1816 level=logging.DEBUG, noiselevel=-1)
1817 else:
1818 # Display the specific atom from SetArg or
1819 # Package types.
1820 uneval = ""
1821 if dep.atom is not dep.atom.unevaluated_atom:
1822 uneval = " (%s)" % (dep.atom.unevaluated_atom,)
1823 writemsg_level(
1824 "%s%s%s required by %s\n" %
1825 ("Parent Dep:".ljust(15), dep.atom, uneval, myparent),
1826 level=logging.DEBUG, noiselevel=-1)
1827
1828 # Ensure that the dependencies of the same package
1829 # are never processed more than once.
1830 previously_added = pkg in self._dynamic_config.digraph
1831
1832 pkgsettings = self._frozen_config.pkgsettings[pkg.root]
1833
1834 arg_atoms = None
1835 if True:
1836 try:
1837 arg_atoms = list(self._iter_atoms_for_pkg(pkg))
1838 except portage.exception.InvalidDependString as e:
1839 if not pkg.installed:
1840 # should have been masked before it was selected
1841 raise
1842 del e
1843
1844 # NOTE: REQUIRED_USE checks are delayed until after
1845 # package selection, since we want to prompt the user
1846 # for USE adjustment rather than have REQUIRED_USE
1847 # affect package selection and || dep choices.
1848 if not pkg.built and pkg._metadata.get("REQUIRED_USE") and \
1849 eapi_has_required_use(pkg.eapi):
1850 required_use_is_sat = check_required_use(
1851 pkg._metadata["REQUIRED_USE"],
1852 self._pkg_use_enabled(pkg),
1853 pkg.iuse.is_valid_flag,
1854 eapi=pkg.eapi)
1855 if not required_use_is_sat:
1856 if dep.atom is not None and dep.parent is not None:
1857 self._add_parent_atom(pkg, (dep.parent, dep.atom))
1858
1859 if arg_atoms:
1860 for parent_atom in arg_atoms:
1861 parent, atom = parent_atom
1862 self._add_parent_atom(pkg, parent_atom)
1863
1864 atom = dep.atom
1865 if atom is None:
1866 atom = Atom("=" + pkg.cpv)
1867 self._dynamic_config._unsatisfied_deps_for_display.append(
1868 ((pkg.root, atom),
1869 {"myparent" : dep.parent, "show_req_use" : pkg}))
1870 self._dynamic_config._skip_restart = True
1871 return 0
1872
1873 if not pkg.onlydeps:
1874
1875 existing_node, existing_node_matches = \
1876 self._check_slot_conflict(pkg, dep.atom)
1877 slot_collision = False
1878 if existing_node:
1879 if existing_node_matches:
1880 # The existing node can be reused.
1881 if pkg != existing_node:
1882 pkg = existing_node
1883 previously_added = True
1884 try:
1885 arg_atoms = list(self._iter_atoms_for_pkg(pkg))
1886 except InvalidDependString as e:
1887 if not pkg.installed:
1888 # should have been masked before
1889 # it was selected
1890 raise
1891
1892 if debug:
1893 writemsg_level(
1894 "%s%s %s\n" % ("Re-used Child:".ljust(15),
1895 pkg, pkg_use_display(pkg,
1896 self._frozen_config.myopts,
1897 modified_use=self._pkg_use_enabled(pkg))),
1898 level=logging.DEBUG, noiselevel=-1)
1899
1900 else:
1901 self._add_slot_conflict(pkg)
1902 if debug:
1903 writemsg_level(
1904 "%s%s %s\n" % ("Slot Conflict:".ljust(15),
1905 existing_node, pkg_use_display(existing_node,
1906 self._frozen_config.myopts,
1907 modified_use=self._pkg_use_enabled(existing_node))),
1908 level=logging.DEBUG, noiselevel=-1)
1909
1910 slot_collision = True
1911
1912 if slot_collision:
1913 # Now add this node to the graph so that self.display()
1914 # can show use flags and --tree portage.output. This node is
1915 # only being partially added to the graph. It must not be
1916 # allowed to interfere with the other nodes that have been
1917 # added. Do not overwrite data for existing nodes in
1918 # self._dynamic_config.mydbapi since that data will be used for blocker
1919 # validation.
1920 # Even though the graph is now invalid, continue to process
1921 # dependencies so that things like --fetchonly can still
1922 # function despite collisions.
1923 pass
1924 elif not previously_added:
1925 self._dynamic_config._slot_pkg_map[pkg.root][pkg.slot_atom] = pkg
1926 self._dynamic_config.mydbapi[pkg.root].cpv_inject(pkg)
1927 self._dynamic_config._filtered_trees[pkg.root]["porttree"].dbapi._clear_cache()
1928 self._dynamic_config._highest_pkg_cache.clear()
1929 self._check_masks(pkg)
1930
1931 if not pkg.installed:
1932 # Allow this package to satisfy old-style virtuals in case it
1933 # doesn't already. Any pre-existing providers will be preferred
1934 # over this one.
1935 try:
1936 pkgsettings.setinst(pkg.cpv, pkg._metadata)
1937 # For consistency, also update the global virtuals.
1938 settings = self._frozen_config.roots[pkg.root].settings
1939 settings.unlock()
1940 settings.setinst(pkg.cpv, pkg._metadata)
1941 settings.lock()
1942 except portage.exception.InvalidDependString:
1943 if not pkg.installed:
1944 # should have been masked before it was selected
1945 raise
1946
1947 if arg_atoms:
1948 self._dynamic_config._set_nodes.add(pkg)
1949
1950 # Do this even for onlydeps, so that the
1951 # parent/child relationship is always known in case
1952 # self._show_slot_collision_notice() needs to be called later.
1953 # If a direct circular dependency is not an unsatisfied
1954 # buildtime dependency then drop it here since otherwise
1955 # it can skew the merge order calculation in an unwanted
1956 # way.
1957 if pkg != dep.parent or \
1958 (