[installed category packages]
class = portage.sets.dbapi.CategorySet
multiset = true
+ repository = vartree
name_pattern = $category/*
</programlisting>
</para>
<listitem><para><varname>category</varname>: Required. The name of an existing ebuild
category which should be used to create the package set.</para>
</listitem>
+ <listitem><para><varname>repository</varname>: Optional, defaults to
+ <parameter>porttree</parameter>. It determines which repository class should
+ be used to create the package set. Valid values for this option are:
+ <parameter>porttree</parameter> (normal ebuild repository),
+ <parameter>vartree</parameter> (installed package repository)
+ and <parameter>bintree</parameter> (local binary package repository).</para>
+ </listitem>
<listitem><para><varname>only_visible</varname>: Optional, defaults to <parameter>true</parameter>.
When set to <parameter>true</parameter> the set will only include visible packages,
when set to <parameter>false</parameter> it will also include masked packages.
from portage.cache.mappings import slot_dict_class
from portage.dep import paren_reduce, use_reduce, \
paren_normalize, paren_enclose, _slot_re
+from portage.const import EPREFIX
from _emerge.Task import Task
if sys.hexversion >= 0x3000000:
"installed", "metadata", "onlydeps", "operation",
"root_config", "type_name",
"category", "counter", "cp", "cpv_split",
- "inherited", "invalid", "iuse", "mtime",
- "pf", "pv_split", "root", "slot", "slot_atom",) + \
+ "inherited", "invalid", "iuse", "masks", "mtime",
+ "pf", "pv_split", "root", "slot", "slot_atom", "visible",) + \
("_use",)
metadata_keys = [
self.category, self.pf = portage.catsplit(self.cpv)
self.cpv_split = portage.catpkgsplit(self.cpv)
self.pv_split = self.cpv_split[1:]
+ self.masks = self._masks()
+ self.visible = self._visible(self.masks)
+
+ def _masks(self):
+ masks = {}
+ settings = self.root_config.settings
+
+ if self.invalid is not None:
+ masks['invalid'] = self.invalid
+
+ if not settings._accept_chost(self.cpv, self.metadata):
+ masks['CHOST'] = self.metadata['CHOST']
+
+ eapi = self.metadata["EAPI"]
+ if not portage.eapi_is_supported(eapi):
+ masks['EAPI.unsupported'] = eapi
+ if portage._eapi_is_deprecated(eapi):
+ masks['EAPI.deprecated'] = eapi
+
+ missing_keywords = settings._getMissingKeywords(
+ self.cpv, self.metadata)
+ if missing_keywords:
+ masks['KEYWORDS'] = missing_keywords
+
+ if self.built and not self.installed:
+ # we can have an old binary which has no EPREFIX information
+ if "EPREFIX" not in self.metadata or not self.metadata["EPREFIX"]:
+ masks['EPREFIX.missing'] = ''
+ if len(self.metadata["EPREFIX"].strip()) < len(EPREFIX):
+ masks['EPREFIX.tooshort'] = self.metadata["EPREFIX"].strip()
+
+ try:
+ missing_properties = settings._getMissingProperties(
+ self.cpv, self.metadata)
+ if missing_properties:
+ masks['PROPERTIES'] = missing_properties
+ except portage.exception.InvalidDependString:
+ # already recorded as 'invalid'
+ pass
+
+ mask_atom = settings._getMaskAtom(self.cpv, self.metadata)
+ if mask_atom is not None:
+ masks['package.mask'] = mask_atom
+
+ system_mask = settings._getProfileMaskAtom(
+ self.cpv, self.metadata)
+ if system_mask is not None:
+ masks['profile.system'] = system_mask
+
+ try:
+ missing_licenses = settings._getMissingLicenses(
+ self.cpv, self.metadata)
+ if missing_licenses:
+ masks['LICENSE'] = missing_licenses
+ except portage.exception.InvalidDependString:
+ # already recorded as 'invalid'
+ pass
+
+ if not masks:
+ masks = None
+
+ return masks
+
+ def _visible(self, masks):
+
+ if masks is not None:
+
+ if 'EAPI.unsupported' in masks:
+ return False
+
+ if self.built and not self.installed and ( \
+ 'EPREFIX.missing' in masks or \
+ 'EPREFIX.tooshort' in masks):
+ return False
+
+ if not self.installed and ( \
+ 'invalid' in masks or \
+ 'CHOST' in masks or \
+ 'EAPI.deprecated' in masks or \
+ 'KEYWORDS' in masks or \
+ 'PROPERTIES' in masks):
+ return False
+
+ if 'package.mask' in masks or \
+ 'profile.system' in masks or \
+ 'LICENSE' in masks:
+ return False
+
+ return True
def _invalid_metadata(self, msg_type, msg):
if self.invalid is None:
from _emerge.SetArg import SetArg
from _emerge.show_invalid_depstring_notice import show_invalid_depstring_notice
from _emerge.UnmergeDepPriority import UnmergeDepPriority
-from _emerge.visible import visible
if sys.hexversion >= 0x3000000:
basestring = str
self.roots = {}
# All Package instances
self._pkg_cache = {}
+ self._highest_license_masked = {}
for myroot in trees:
self.trees[myroot] = {}
# Create a RootConfig instance that references
msg.append("satisfy simultaneously. If such a conflict exists in ")
msg.append("the dependencies of two different packages, then those ")
msg.append("packages can not be installed simultaneously.")
+ backtrack_opt = self._frozen_config.myopts.get('--backtrack')
+ if not self._dynamic_config._allow_backtracking and \
+ (backtrack_opt is None or \
+ (backtrack_opt > 0 and backtrack_opt < 30)):
+ msg.append(" You may want to try a larger value of the ")
+ msg.append("--backtrack option, such as --backtrack=30, ")
+ msg.append("in order to see if that will solve this conflict ")
+ msg.append("automatically.")
from formatter import AbstractFormatter, DumbWriter
f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
self._dynamic_config._slot_pkg_map[pkg.root][pkg.slot_atom] = pkg
self._dynamic_config.mydbapi[pkg.root].cpv_inject(pkg)
self._dynamic_config._filtered_trees[pkg.root]["porttree"].dbapi._clear_cache()
+ self._check_masks(pkg)
if not pkg.installed:
# Allow this package to satisfy old-style virtuals in case it
dep_stack.append(pkg)
return 1
+ def _check_masks(self, pkg):
+
+ slot_key = (pkg.root, pkg.slot_atom)
+
+ # Check for upgrades in the same slot that are
+ # masked due to a LICENSE change in a newer
+ # version that is not masked for any other reason.
+ other_pkg = self._frozen_config._highest_license_masked.get(slot_key)
+ if other_pkg is not None and pkg < other_pkg:
+ self._dynamic_config._masked_license_updates.add(other_pkg)
+
def _add_parent_atom(self, pkg, parent_atom):
parent_atoms = self._dynamic_config._parent_atoms.get(pkg)
if parent_atoms is None:
pkg, existing = ret
if pkg is not None:
settings = pkg.root_config.settings
- if visible(settings, pkg) and not (pkg.installed and \
+ if pkg.visible and not (pkg.installed and \
settings._getMissingKeywords(pkg.cpv, pkg.metadata)):
self._dynamic_config._visible_pkgs[pkg.root].cpv_inject(pkg)
return ret
# here, packages that have been masked since they
# were installed can be automatically downgraded
# to an unmasked version.
- try:
- if not visible(pkgsettings, pkg):
- continue
- except portage.exception.InvalidDependString:
- if not installed:
- continue
+
+ if not pkg.visible:
+ continue
# Enable upgrade or downgrade to a version
# with visible KEYWORDS when the installed
except portage.exception.PackageNotFound:
continue
else:
- if not visible(pkgsettings, pkg_eb):
+ if not pkg_eb.visible:
continue
# Calculation of USE for unbuilt ebuilds is relatively
installed=installed, metadata=metadata, onlydeps=onlydeps,
root_config=root_config, type_name=type_name)
self._frozen_config._pkg_cache[pkg] = pkg
+
+ if not pkg.visible and \
+ 'LICENSE' in pkg.masks and len(pkg.masks) == 1:
+ slot_key = (pkg.root, pkg.slot_atom)
+ other_pkg = self._frozen_config._highest_license_masked.get(slot_key)
+ if other_pkg is None or pkg > other_pkg:
+ self._frozen_config._highest_license_masked[slot_key] = pkg
+
return pkg
def _validate_blockers(self):
# packages masked by license, since the user likely wants
# to adjust ACCEPT_LICENSE.
if pkg in final_db:
- if pkg_in_graph and not visible(pkgsettings, pkg):
- self._dynamic_config._masked_installed.add(pkg)
- elif pkgsettings._getMissingLicenses(pkg.cpv, pkg.metadata):
+ if not pkg.visible and \
+ (pkg_in_graph or 'LICENSE' in pkg.masks):
self._dynamic_config._masked_installed.add(pkg)
- elif pkg_in_graph or complete or deep:
- # Check for upgrades in the same slot that are
- # masked due to a LICENSE change in a newer
- # version that is not masked for any other reason.
- # Only do this for packages that are already in
- # the graph, or complete or deep graphs, since
- # otherwise it is likely a waste of time.
- got_mask = False
- for db, pkg_type, built, installed, db_keys in dbs:
- if installed:
- continue
- if got_mask:
- break
- for upgrade_pkg in self._iter_match_pkgs(
- root_config, pkg_type, pkg.slot_atom):
- if upgrade_pkg <= pkg:
- break
- if not visible(pkgsettings,
- upgrade_pkg, ignore=('LICENSE',)):
- continue
- if pkgsettings._getMissingLicenses(
- upgrade_pkg.cpv, upgrade_pkg.metadata):
- self._dynamic_config._masked_license_updates.add(upgrade_pkg)
- got_mask = True
- break
+ else:
+ self._check_masks(pkg)
blocker_atoms = None
blockers = None
for blocker in blocker_nodes:
if not myblocker_uninstalls.child_nodes(blocker):
myblocker_uninstalls.remove(blocker)
- solved_blockers.add(blocker)
+ if blocker not in \
+ self._dynamic_config._unsolvable_blockers:
+ solved_blockers.add(blocker)
retlist.append(node)
# it serves as an indicator that blocking packages
# will be temporarily installed simultaneously.
for blocker in solved_blockers:
- retlist.append(Blocker(atom=blocker.atom,
- root=blocker.root, eapi=blocker.eapi,
- satisfied=True))
+ blocker.satisfied = True
+ retlist.append(blocker)
unsolvable_blockers = set(self._dynamic_config._unsolvable_blockers.leaf_nodes())
for node in myblocker_uninstalls.root_nodes():
unsatisfied_blockers = []
ordered_nodes = []
for x in mylist:
- if isinstance(x, Blocker) and not x.satisfied:
- unsatisfied_blockers.append(x)
+ if isinstance(x, Blocker):
+ counters.blocks += 1
+ if x.satisfied:
+ ordered_nodes.append(x)
+ counters.blocks_satisfied += 1
+ else:
+ unsatisfied_blockers.append(x)
else:
ordered_nodes.append(x)
else:
blocker_style = "PKG_BLOCKER"
addl = "%s %s " % (colorize(blocker_style, "B"), fetch)
- if ordered:
- counters.blocks += 1
- if x.satisfied:
- counters.blocks_satisfied += 1
resolved = portage.dep_expand(
str(x.atom).lstrip("!"), mydb=vardb, settings=pkgsettings)
if "--columns" in self._frozen_config.myopts and "--quiet" in self._frozen_config.myopts:
else:
seen_nodes.add(node)
- if isinstance(node, Package):
+ if isinstance(node, (Blocker, Package)):
display_list.append((node, depth, True))
else:
depth = -1
del display_list[i]
continue
if ordered and isinstance(node, Package) \
- and node.operation == 'merge':
+ and node.operation in ('merge', 'uninstall'):
last_merge_depth = depth
continue
if depth >= last_merge_depth or \
continue
raise
- if "merge" == pkg.operation and \
- not visible(root_config.settings, pkg):
+ if "merge" == pkg.operation and not pkg.visible:
if skip_masked:
masked_tasks.append(Dependency(root=pkg.root, parent=pkg))
else:
arg = None
if arg:
return False
- if pkg.installed:
- try:
- if not visible(
- self._depgraph._frozen_config.pkgsettings[pkg.root], pkg):
- return False
- except portage.exception.InvalidDependString:
- pass
+ if pkg.installed and not pkg.visible:
+ return False
in_graph = self._depgraph._dynamic_config._slot_pkg_map[
self._root].get(pkg.slot_atom)
if in_graph is None:
# conflicts).
highest_visible, in_graph = self._depgraph._select_package(
self._root, pkg.slot_atom)
- if pkg != highest_visible:
+ # Note: highest_visible is not necessarily the real highest
+ # visible, especially when --update is not enabled, so use
+ # < operator instead of !=.
+ if pkg < highest_visible:
return False
elif in_graph != pkg:
# Mask choices for packages that would trigger a slot
backtrack_max = myopts.get('--backtrack', 5)
runtime_pkg_mask = None
- allow_backtracking = True
+ allow_backtracking = backtrack_max > 0
backtracked = 0
frozen_config = _frozen_depgraph_config(settings, trees,
myopts, spinner)
from portage.util import writemsg_stdout
from _emerge.Package import Package
-from _emerge.visible import visible
class search(object):
pkg_type = "installed"
elif built:
pkg_type = "binary"
- return visible(self.settings,
- Package(type_name=pkg_type, root_config=self.root_config,
- cpv=cpv, built=built, installed=installed, metadata=metadata))
+ return Package(type_name=pkg_type,
+ root_config=self.root_config,
+ cpv=cpv, built=built, installed=installed,
+ metadata=metadata).visible
def _xmatch(self, level, atom):
"""
+++ /dev/null
-# Copyright 1999-2009 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-# $Id$
-
-import portage
-
-def visible(pkgsettings, pkg, ignore=None):
- """
- Check if a package is visible. This can raise an InvalidDependString
- exception if LICENSE is invalid.
- TODO: optionally generate a list of masking reasons
- @rtype: Boolean
- @returns: True if the package is visible, False otherwise.
- """
- if not pkg.metadata["SLOT"]:
- return False
- if not pkg.installed:
- if pkg.invalid:
- return False
- if not pkgsettings._accept_chost(pkg.cpv, pkg.metadata):
- return False
- if pkg.built and not pkg.installed:
- # we can have an old binary which has no EPREFIX information
- if "EPREFIX" not in pkg.metadata or not pkg.metadata["EPREFIX"]:
- return False
- if len(pkg.metadata["EPREFIX"].strip()) < len(pkgsettings["EPREFIX"]):
- return False
- eapi = pkg.metadata["EAPI"]
- if not portage.eapi_is_supported(eapi):
- return False
- if not pkg.installed:
- if portage._eapi_is_deprecated(eapi):
- return False
- if pkgsettings._getMissingKeywords(pkg.cpv, pkg.metadata):
- return False
- try:
- if pkgsettings._getMissingProperties(pkg.cpv, pkg.metadata):
- return False
- except portage.exception.InvalidDependString:
- return False
- if pkgsettings._getMaskAtom(pkg.cpv, pkg.metadata):
- return False
- if pkgsettings._getProfileMaskAtom(pkg.cpv, pkg.metadata):
- return False
- try:
- if pkgsettings._getMissingLicenses(pkg.cpv, pkg.metadata):
- if ignore is None or 'LICENSE' not in ignore:
- return False
- except portage.exception.InvalidDependString:
- return False
- return True
else:
ret=os.rename(src,dest)
renamefailed=0
- except SystemExit as e:
- raise
- except Exception as e:
- if e[0]!=errno.EXDEV:
+ except OSError as e:
+ if e.errno != errno.EXDEV:
# Some random error.
print(_("!!! Failed to move %(src)s to %(dest)s") % {"src": src, "dest": dest})
print("!!!",e)
myatoms.append(cp)
self._setAtoms(myatoms)
+ def _builderGetRepository(cls, options, repositories):
+ repository = options.get("repository", "porttree")
+ if not repository in repositories:
+ raise SetConfigError(_("invalid repository class '%s'") % repository)
+ return repository
+ _builderGetRepository = classmethod(_builderGetRepository)
+
def _builderGetVisible(cls, options):
return get_boolean(options, "only_visible", True)
_builderGetVisible = classmethod(_builderGetVisible)
if not category in settings.categories:
raise SetConfigError(_("invalid category name '%s'") % category)
+ repository = cls._builderGetRepository(options, trees.keys())
visible = cls._builderGetVisible(options)
- return CategorySet(category, dbapi=trees["porttree"].dbapi, only_visible=visible)
+ return CategorySet(category, dbapi=trees[repository].dbapi, only_visible=visible)
singleBuilder = classmethod(singleBuilder)
def multiBuilder(cls, options, settings, trees):
else:
categories = settings.categories
+ repository = cls._builderGetRepository(options, trees.keys())
visible = cls._builderGetVisible(options)
name_pattern = options.get("name_pattern", "$category/*")
raise SetConfigError(_("name_pattern doesn't include $category placeholder"))
for cat in categories:
- myset = CategorySet(cat, trees["porttree"].dbapi, only_visible=visible)
+ myset = CategorySet(cat, trees[repository].dbapi, only_visible=visible)
myname = name_pattern.replace("$category", cat)
myname = myname.replace("${category}", cat)
rValue[myname] = myset
--- /dev/null
+# Copyright 2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+from portage.const import PORTAGE_PYM_PATH
+from portage.tests import TestCase
+from portage import os
+from portage import _encodings
+from portage import _unicode_decode
+
+import py_compile
+
+class CompileModulesTestCase(TestCase):
+
+ def testCompileModules(self):
+ for parent, dirs, files in os.walk(PORTAGE_PYM_PATH):
+ parent = _unicode_decode(parent,
+ encoding=_encodings['fs'], errors='strict')
+ for x in files:
+ x = _unicode_decode(x,
+ encoding=_encodings['fs'], errors='strict')
+ if x[-3:] == '.py':
+ py_compile.compile(os.path.join(parent, x), doraise=True)