else:
yield flag
+class DepPriority(object):
+ """
+ This class generates an integer priority level based of various
+ attributes of the dependency relationship. Attributes can be assigned
+ at any time and the new integer value will be generated on calls to the
+ __int__() method. Rich comparison operators are supported.
+
+ The boolean attributes that affect the integer value are "satisfied",
+ "buildtime", "runtime", and "system". Various combinations of
+ attributes lead to the following priority levels:
+
+ Combination of properties Priority level
+
+ not satisfied and buildtime 0
+ not satisfied and runtime -1
+ satisfied and buildtime -2
+ satisfied and runtime -3
+ (none of the above) -4
+
+ Several integer constants are defined for categorization of priority
+ levels:
+
+ MEDIUM The upper boundary for medium dependencies.
+ SOFT The upper boundary for soft dependencies.
+ MIN The lower boundary for soft dependencies.
+ """
+ __slots__ = ["__weakref__", "satisfied", "buildtime", "runtime"]
+ MEDIUM = -1
+ SOFT = -2
+ MIN = -4
+ def __init__(self, **kwargs):
+ for myattr in self.__slots__:
+ if myattr == "__weakref__":
+ continue
+ myvalue = kwargs.get(myattr, False)
+ setattr(self, myattr, myvalue)
+ def __int__(self):
+ if not self.satisfied:
+ if self.buildtime:
+ return 0
+ if self.runtime:
+ return -1
+ if self.buildtime:
+ return -2
+ if self.runtime:
+ return -3
+ return -4
+ def __lt__(self, other):
+ return int(self) < other
+ def __le__(self, other):
+ return int(self) <= other
+ def __eq__(self, other):
+ return int(self) == other
+ def __ne__(self, other):
+ return int(self) != other
+ def __gt__(self, other):
+ return int(self) > other
+ def __ge__(self, other):
+ return int(self) >= other
+ def copy(self):
+ import copy
+ return copy.copy(self)
+ def __str__(self):
+ myvalue = int(self)
+ if myvalue > self.MEDIUM:
+ return "hard"
+ if myvalue > self.SOFT:
+ return "medium"
+ return "soft"
+
class depgraph:
pkg_tree_map = {
self.blocker_parents = {}
def create(self, mybigkey, myparent=None, addme=1, myuse=None,
- priority=digraph.HARD, rev_dep=False, arg=None):
+ priority=DepPriority(), rev_dep=False, arg=None):
"""
Fills the digraph with nodes comprised of packages to merge.
mybigkey is the package spec of the package to merge.
if addme and "--buildpkgonly" not in self.myopts and myparent:
mybigkey[1] = myparent.split()[1]
self.digraph.addnode(" ".join(mybigkey), myparent,
- priority=digraph.SOFT)
+ priority=DepPriority())
return 1
if not arg:
arg = portage.best_match_to_list(mykey, self.args_keys)
try:
if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
- myuse=myuse, parent_arg=arg):
+ myuse=myuse, priority=DepPriority(buildtime=True),
+ parent_arg=arg):
return 0
"""RDEPEND is soft by definition. However, in order to ensure
correct merge order, we make it a hard dependency. Otherwise, a
dependencies not being installed yet.
"""
if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
- myuse=myuse, priority=digraph.MEDIUM, parent_arg=arg):
+ myuse=myuse, priority=DepPriority(runtime=True),
+ parent_arg=arg):
return 0
if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
# Post Depend -- Add to the list without a parent, as it depends
# on a package being present AND must be built after that package.
if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
- myuse=myuse, priority=digraph.SOFT, rev_deps=True, parent_arg=arg):
+ myuse=myuse, priority=DepPriority(), rev_deps=True,
+ parent_arg=arg):
return 0
except ValueError, e:
pkgs = e.args[0]
return match
def select_dep(self, myroot, depstring, myparent=None, arg=None,
- myuse=None, raise_on_missing=False, priority=digraph.HARD, rev_deps=False,
- parent_arg=None):
+ myuse=None, raise_on_missing=False, priority=DepPriority(),
+ rev_deps=False, parent_arg=None):
""" Given a depstring, create the depgraph such that all dependencies are satisfied.
myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
myparent = the node whose depstring is being passed in
iuses = set(filter_iuse_defaults(
bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
- pkgsettings.setcpv(myeb_pkg, mydb=portdb)
+ mydb = None
+ if "--usepkgonly" not in self.myopts and myeb:
+ mydb = portdb
+ pkgsettings.setcpv(myeb, mydb=mydb)
now_use = pkgsettings["USE"].split()
forced_flags = set()
forced_flags.update(pkgsettings.useforce)
if myparent:
#we are a dependency, so we want to be unconditionally added
- mypriority = priority
- if mypriority > digraph.SOFT and vardb.match(x):
- mypriority = digraph.SOFT
+ mypriority = priority.copy()
+ if vardb.match(x):
+ mypriority.satisfied = True
if not self.create(selected_pkg[0:3], myparent,
myuse=selected_pkg[-1], priority=mypriority,
rev_dep=rev_deps, arg=arg):
enforce correct merge order."""
fakedb = self.mydbapi[myroot]
new_pkgs = []
+ unresolveable = False
for cpv in blocked_pkgs:
myslot = vardb.aux_get(cpv, ["SLOT"])[0]
myslot_atom = "%s:%s" % (portage.dep_getkey(cpv), myslot)
- new_pkgs.append(
- (myslot_atom, fakedb.match(myslot_atom)[0]))
+ mymatches = fakedb.match(myslot_atom)
+ if mymatches:
+ new_pkgs.append((myslot_atom, mymatches[0]))
+ else:
+ """There's an installed package that's blocked and
+ there's no upgrade found to invalidate it, so leave
+ this blocker in the digraph."""
+ unresolveable = True
+ break
+ if unresolveable:
+ continue
+
for parent in self.digraph.parent_nodes(blocker):
ptype, proot, pcpv, pstatus = parent.split()
pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
continue
# Enforce correct merge order with a hard dep.
node = self.pkg_node_map[pkg]
- self.digraph.addnode(node, parent)
+ self.digraph.addnode(node, parent,
+ priority=DepPriority(buildtime=True))
"""Count references to this blocker so that it can be
invalidated after nodes referencing it have been merged."""
self.blocker_digraph.addnode(node, blocker)
get_nodes = mygraph.root_nodes
else:
get_nodes = mygraph.leaf_nodes
+ ignore_priority_range = [None]
+ ignore_priority_range.extend(
+ xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
while not mygraph.empty():
- for ignore_priority in \
- (digraph.NONE, digraph.SOFT, digraph.MEDIUM):
+ for ignore_priority in ignore_priority_range:
nodes = get_nodes(ignore_priority=ignore_priority)
if nodes:
break
selected_nodes = None
if nodes:
- if ignore_priority <= digraph.SOFT:
+ if ignore_priority <= DepPriority.SOFT:
selected_nodes = [nodes[0]]
else:
"""Recursively gather a group of nodes that RDEPEND on
return False
selected_nodes.add(node)
for child in mygraph.child_nodes(node,
- ignore_priority=digraph.SOFT):
+ ignore_priority=DepPriority.SOFT):
if not gather_deps(
mergeable_nodes, selected_nodes, child):
return False
for node in myblockers.root_nodes():
retlist.append(node.split())
for parent in self.blocker_parents[node]:
- self.digraph.add(node, parent, priority=digraph.SOFT)
+ self.digraph.add(node, parent, priority=DepPriority())
return retlist
show_blocker_docs_link()
sys.exit(1)
if mergecount==0:
- if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
+ if "--noreplace" in myopts and favorites:
+ print
+ for x in favorites:
+ print " %s %s" % (good("*"), x)
+ prompt="Would you like to add these packages to your world favorites?"
+ elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
prompt="Nothing to merge; would you like to auto-clean packages?"
else:
print
#beautiful directed graph object
class digraph:
- NONE = -1
- SOFT = 0
- MEDIUM = 1
- HARD = 2
def __init__(self):
"""Create an empty digraph"""
self.nodes = {}
self.order = []
- def add(self, node, parent, priority=2):
+ def add(self, node, parent, priority=0):
"""Adds the specified node with the specified parent.
If the dep is a soft-dep and the node already has a hard
"""Return a list of all nodes in the graph"""
return self.order[:]
- def child_nodes(self, node, ignore_priority=-1):
+ def child_nodes(self, node, ignore_priority=None):
"""Return all children of the specified node"""
- if ignore_priority == -1:
+ if ignore_priority is None:
return self.nodes[node][0].keys()
children = []
for child, priority in self.nodes[node][0].iteritems():
"""Return all parents of the specified node"""
return self.nodes[node][1].keys()
- def leaf_nodes(self, ignore_priority=-1):
+ def leaf_nodes(self, ignore_priority=None):
"""Return all nodes that have no children
If ignore_soft_deps is True, soft deps are not counted as
leaf_nodes.append(node)
return leaf_nodes
- def root_nodes(self, ignore_priority=-1):
+ def root_nodes(self, ignore_priority=None):
"""Return all nodes that have no parents.
If ignore_soft_deps is True, soft deps are not counted as
return leaf_nodes[0]
return None
- def hasallzeros(self, ignore_priority=-1):
+ def hasallzeros(self, ignore_priority=None):
return len(self.leaf_nodes(ignore_priority=ignore_priority)) == \
len(self.order)
print "(no children)"
for child in self.nodes[node][0]:
print " ",child,
- if self.nodes[node][0][child] == self.HARD:
- print "(hard)"
- elif self.nodes[node][0][child] == self.MEDIUM:
- print "(medium)"
- else:
- print "(soft)"
+ print "(%s)" % self.nodes[node][0][child]
mylist = []
for myconfig in config_list:
if var in myconfig:
- mylist.extend(myconfig[var].split())
+ mylist.extend(filter(None, myconfig[var].split()))
del myconfig[var] # prepare for env.update(myconfig)
if mylist:
env[var] = " ".join(mylist)
mylist = []
for myconfig in config_list:
if var in myconfig:
- mylist.extend(myconfig[var].split(":"))
+ mylist.extend(filter(None, myconfig[var].split(":")))
del myconfig[var] # prepare for env.update(myconfig)
if mylist:
env[var] = ":".join(mylist)
self.configdict["pkginternal"]["USE"] = pkginternaluse
defaults = []
for i in xrange(len(self.profiles)):
- profile_use = self.make_defaults_use[i]
+ defaults.append(self.make_defaults_use[i])
cpdict = self.pkgprofileuse[i].get(cp, None)
if cpdict:
best_match = best_match_to_list(self.mycpv, cpdict.keys())
if best_match:
- profile_use += " " + cpdict[best_match]
- defaults.append(profile_use)
+ defaults.append(cpdict[best_match])
self.configdict["defaults"]["USE"] = " ".join(defaults)
useforce = []
for i in xrange(len(self.profiles)):