status = "nomerge"
self._digraph_node = (self.type_name, self.root, self.cpv, status)
+ def __lt__(self, other):
+ other_split = portage.catpkgsplit(other.cpv)
+ self_split = portage.catpkgsplit(self.cpv)
+ if other_split[:2] != self_split[:2]:
+ return False
+ if portage.pkgcmp(self_split[1:], other_split[1:]) < 0:
+ return True
+ return False
+
+ def __gt__(self, other):
+ other_split = portage.catpkgsplit(other.cpv)
+ self_split = portage.catpkgsplit(self.cpv)
+ if other_split[:2] != self_split[:2]:
+ return False
+ if portage.pkgcmp(self_split[1:], other_split[1:]) > 0:
+ return True
+ return False
+
def __eq__(self, other):
return self._digraph_node == other
def __ne__(self, other):
del trees
self.digraph=portage.digraph()
- # Tracks simple parent/child relationships (PDEPEND relationships are
- # not reversed).
- self._parent_child_digraph = digraph()
# contains all sets added to the graph
self._sets = {}
# contains atoms given as arguments
for node in slot_nodes:
msg.append(indent)
msg.append(str(node))
- parents = self._parent_child_digraph.parent_nodes(node)
+ parents = self.digraph.parent_nodes(node)
if parents:
omitted_parents = 0
if len(parents) > max_parents:
if existing_node:
if pkg.cpv == existing_node.cpv:
# The existing node can be reused.
- self._parent_child_digraph.add(existing_node, myparent)
if args:
for arg in args:
- self._parent_child_digraph.add(existing_node, arg)
+ self.digraph.add(existing_node, arg,
+ priority=priority)
# If a direct circular dependency is not an unsatisfied
# buildtime dependency then drop it here since otherwise
# it can skew the merge order calculation in an unwanted
# Do this even when addme is False (--onlydeps) so that the
# parent/child relationship is always known in case
# self._show_slot_collision_notice() needs to be called later.
- self._parent_child_digraph.add(pkg, myparent)
+ if pkg.onlydeps:
+ self.digraph.add(pkg, myparent, priority=priority)
if args:
for arg in args:
- self._parent_child_digraph.add(pkg, arg)
+ self.digraph.add(pkg, arg, priority=priority)
""" This section determines whether we go deeper into dependencies or not.
We want to go deeper on a few occasions:
strict = mytype != "installed"
try:
for dep_root, dep_string, dep_priority in deps:
+ if pkg.onlydeps:
+ # Decrease priority so that --buildpkgonly
+ # hasallzeros() works correctly.
+ dep_priority = DepPriority()
if not dep_string:
continue
if debug:
myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
for myslot in myslots:
yield "%s:%s" % (mykey, myslot)
- # In addition to any installed slots, also try to pull
- # in the latest new slot that may be available.
- yield atom
def _iter_args_for_pkg(self, pkg):
# TODO: add multiple $ROOT support
# atoms could be a property of the set itself.
greedy_atoms = []
for arg in args:
+ # In addition to any installed slots, also try to pull
+ # in the latest new slot that may be available.
greedy_atoms.append(arg)
if not isinstance(arg, (AtomArg, PackageArg)):
continue
while args:
arg = args.pop()
for atom in arg.set:
+ atom_cp = portage.dep_getkey(atom)
try:
pprovided = pprovideddict.get(portage.dep_getkey(atom))
if pprovided and portage.match_from_list(atom, pprovided):
return 0, myfavorites
self._missing_args.append((arg, atom))
continue
+ if atom_cp != pkg.cp:
+ # For old-style virtuals, we need to repeat the
+ # package.provided check against the selected package.
+ expanded_atom = atom.replace(atom_cp, pkg.cp)
+ pprovided = pprovideddict.get(pkg.cp)
+ if pprovided and \
+ portage.match_from_list(expanded_atom, pprovided):
+ # A provided package has been
+ # specified on the command line.
+ self._pprovided_args.append((arg, atom))
+ continue
if pkg.installed and "selective" not in self.myparams:
self._unsatisfied_deps_for_display.append(
((myroot, atom), {}))
portdb = self.roots[root].trees["porttree"].dbapi
# List of acceptable packages, ordered by type preference.
matched_packages = []
+ highest_version = None
+ atom_cp = portage.dep_getkey(atom)
existing_node = None
myeb = None
usepkgonly = "--usepkgonly" in self.myopts
if not installed:
# masked by corruption
continue
+ pkg = Package(built=built, cpv=cpv, installed=installed,
+ metadata=metadata, type_name=pkg_type)
if not installed:
if myarg:
found_available_arg = True
- if not visible(pkgsettings, Package(built=built,
- cpv=cpv, installed=installed, metadata=metadata,
- type_name=pkg_type)):
+ if not visible(pkgsettings, pkg):
continue
+ if pkg.cp == atom_cp:
+ if highest_version is None:
+ highest_version = pkg
+ elif pkg > highest_version:
+ highest_version = pkg
# At this point, we've found the highest visible
# match from the current repo. Any lower versions
# from this repo are ignored, so this so the loop
cpv_slot = "%s:%s" % \
(e_pkg.cpv, e_pkg.metadata["SLOT"])
if portage.dep.match_from_list(atom, [cpv_slot]):
- matched_packages.append(e_pkg)
- existing_node = e_pkg
+ if highest_version and \
+ e_pkg.cp == atom_cp and \
+ e_pkg < highest_version and \
+ e_pkg.slot_atom != highest_version.slot_atom:
+ # There is a higher version available in a
+ # different slot, so this existing node is
+ # irrelevant.
+ pass
+ else:
+ matched_packages.append(e_pkg)
+ existing_node = e_pkg
break
# Compare built package to current config and
# reject the built package if necessary.
setconfig = root_config.setconfig
args = []
# Reuse existing SetArg instances when available.
- for arg in self._parent_child_digraph.root_nodes():
+ for arg in self.digraph.root_nodes():
if not isinstance(arg, SetArg):
continue
if arg.root_config != root_config:
tree_nodes = []
display_list = []
- mygraph = self._parent_child_digraph
+ mygraph = self.digraph
i = 0
depth = 0
shown_edges = set()
repo_name = self.roots[myroot].settings.get("PORTAGE_BINHOST")
else:
repo_name = metadata["repository"]
+ built = pkg_type != "ebuild"
+ installed = pkg_type == "installed"
if pkg_type == "ebuild":
ebuild_path = portdb.findname(pkg_key)
if not ebuild_path: # shouldn't happen
repo_path_real = repo_name
else:
repo_path_real = portdb.getRepositoryPath(repo_name)
+ pkg_node = Package(type_name=pkg_type, root=myroot,
+ cpv=pkg_key, built=built, installed=installed,
+ metadata=metadata)
pkg_use = metadata["USE"].split()
try:
restrict = flatten(use_reduce(paren_reduce(
mergecount=0
for x in mymergelist:
- mergecount+=1
pkg_type = x[0]
+ if pkg_type == "blocks":
+ continue
+ mergecount+=1
myroot=x[1]
pkg_key = x[2]
pkgindex=2
raise AssertionError("Package type: '%s'" % pkg_type)
metadata.update(izip(metadata_keys,
mydbapi.aux_get(pkg_key, metadata_keys)))
+ built = pkg_type != "ebuild"
+ installed = pkg_type == "installed"
+ pkg = Package(type_name=pkg_type, root=myroot,
+ cpv=pkg_key, built=built, installed=installed,
+ metadata=metadata)
if x[0]=="blocks":
pkgindex=3
y = portdb.findname(pkg_key)
"--fetch-all-uri" not in self.myopts:
# Figure out if we need a restart.
- if myroot == "/" and \
- portage.dep_getkey(pkg_key) == "sys-apps/portage":
+ if myroot == "/" and pkg.cp == "sys-apps/portage":
if len(mymergelist) > mergecount and EPREFIX == BPREFIX:
emergelog(xterm_titles,
" ::: completed emerge ("+ \
"PORTAGE_ECLASS_WARNING_ENABLE", "PORTAGE_ELOG_CLASSES",
"PORTAGE_ELOG_MAILFROM", "PORTAGE_ELOG_MAILSUBJECT",
"PORTAGE_ELOG_MAILURI", "PORTAGE_ELOG_SYSTEM",
- "PORTAGE_FETCH_CHECKSUM_TRY_MIRRORS", "PORTAGE_GPG_DIR",
+ "PORTAGE_FETCH_CHECKSUM_TRY_MIRRORS", "PORTAGE_FETCH_RESUME_MIN_SIZE",
+ "PORTAGE_GPG_DIR",
"PORTAGE_GPG_KEY", "PORTAGE_PACKAGE_EMPTY_ABORT",
"PORTAGE_RSYNC_EXTRA_OPTS", "PORTAGE_RSYNC_OPTS",
"PORTAGE_RSYNC_RETRIES", "PORTAGE_USE", "PORT_LOGDIR",
os.rename(filename, temp_filename)
return temp_filename
+_fetch_resume_size_re = re.compile('(^[\d]+)([KMGTPEZY]?$)')
+
+_size_suffix_map = {
+ '' : 0,
+ 'K' : 10,
+ 'M' : 20,
+ 'G' : 30,
+ 'T' : 40,
+ 'P' : 50,
+ 'E' : 60,
+ 'Z' : 70,
+ 'Y' : 80,
+}
+
def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks",use_locks=1, try_mirrors=1):
"fetch files. Will use digest file if available."
checksum_failure_max_tries = v
del v
+ fetch_resume_size_default = "350K"
+ fetch_resume_size = mysettings.get("PORTAGE_FETCH_RESUME_MIN_SIZE")
+ if fetch_resume_size is not None:
+ fetch_resume_size = "".join(fetch_resume_size.split())
+ if not fetch_resume_size:
+ # If it's undefined or empty, silently use the default.
+ fetch_resume_size = fetch_resume_size_default
+ match = _fetch_resume_size_re.match(fetch_resume_size)
+ if match is None or \
+ (match.group(2).upper() not in _size_suffix_map):
+ writemsg("!!! Variable PORTAGE_FETCH_RESUME_MIN_SIZE" + \
+ " contains an unrecognized format: '%s'\n" % \
+ mysettings["PORTAGE_FETCH_RESUME_MIN_SIZE"], noiselevel=-1)
+ writemsg("!!! Using PORTAGE_FETCH_RESUME_MIN_SIZE " + \
+ "default value: %s\n" % fetch_resume_size_default,
+ noiselevel=-1)
+ fetch_resume_size = None
+ if fetch_resume_size is None:
+ fetch_resume_size = fetch_resume_size_default
+ match = _fetch_resume_size_re.match(fetch_resume_size)
+ fetch_resume_size = int(match.group(1)) * \
+ 2 ** _size_suffix_map[match.group(2).upper()]
+
# Behave like the package has RESTRICT="primaryuri" after a
# couple of checksum failures, to increase the probablility
# of success before checksum_failure_max_tries is reached.
if fetched != 2 and has_space:
#we either need to resume or start the download
- #you can't use "continue" when you're inside a "try" block
- if fetched==1:
+ if fetched == 1:
+ try:
+ mystat = os.stat(myfile_path)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ raise
+ del e
+ fetched = 0
+ else:
+ if mystat.st_size < fetch_resume_size:
+ writemsg((">>> Deleting distfile with size " + \
+ "%d (smaller than " "PORTAGE_FETCH_RESU" + \
+ "ME_MIN_SIZE)\n") % mystat.st_size)
+ try:
+ os.unlink(myfile_path)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ raise
+ del e
+ fetched = 0
+ if fetched == 1:
#resume mode:
writemsg(">>> Resuming download...\n")
locfetch=resumecommand
avail_slot = "%s:%s" % (dep_getkey(atom),
mydbapi.aux_get(avail_pkg, ["SLOT"])[0])
elif not avail_pkg:
- has_mask = False
- if hasattr(mydbapi, "xmatch"):
- has_mask = bool(mydbapi.xmatch("match-all", atom))
- if (selective or use_binaries or not has_mask):
+ if selective:
avail_pkg = vardb.match(atom)
if avail_pkg:
avail_pkg = avail_pkg[-1] # highest (ascending order)
for myslot in intersecting_slots:
myversion = versions[myslot]
o_version = o_versions[myslot]
- if myversion != o_version:
- if myversion == best([myversion, o_version]):
+ difference = pkgcmp(catpkgsplit(myversion)[1:],
+ catpkgsplit(o_version)[1:])
+ if difference:
+ if difference > 0:
has_upgrade = True
else:
has_downgrade = True
writemsg("virts[%s]: %s\n" % (str(mykey),virts[mykey]), 1)
mykey_orig = mykey[:]
for vkey in virts[mykey]:
- if mydb.cp_list(vkey,use_cache=use_cache):
+ # The virtuals file can contain a versioned atom, so
+ # it may be necessary to remove the operator and
+ # version from the atom before it is passed into
+ # dbapi.cp_list().
+ if mydb.cp_list(dep_getkey(vkey), use_cache=use_cache):
mykey = vkey
writemsg("virts chosen: %s\n" % (mykey), 1)
break