class Blocker(Task):
__hash__ = Task.__hash__
- __slots__ = ("root", "atom", "cp", "eapi", "satisfied")
+ __slots__ = ("root", "atom", "cp", "eapi", "priority", "satisfied")
def __init__(self, **kwargs):
Task.__init__(self, **kwargs)
# the parent is or will be installed.
blocker = Blocker(atom=dep.atom,
eapi=dep.parent.metadata["EAPI"],
- root=dep.parent.root)
+ priority=dep.priority, root=dep.parent.root)
self._dynamic_config._blocker_parents.add(blocker, dep.parent)
return 1
# due to the performance penalty that is incurred by all the
# additional dep_check calls that are required.
- dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
+ # For installed packages, always ignore blockers from DEPEND since
+ # only runtime dependencies should be relevant for packages that
+ # are already built.
+ dep_keys = ["RDEPEND", "PDEPEND"]
for myroot in self._frozen_config.trees:
vardb = self._frozen_config.trees[myroot]["vartree"].dbapi
portdb = self._frozen_config.trees[myroot]["porttree"].dbapi
self._dynamic_config._irrelevant_blockers.child_nodes(pkg))
except KeyError:
pass
+ if blockers:
+ # Select just the runtime blockers.
+ blockers = [blocker for blocker in blockers \
+ if blocker.priority.runtime or \
+ blocker.priority.runtime_post]
if blockers is not None:
blockers = set(blocker.atom for blocker in blockers)
try:
for atom in blocker_atoms:
blocker = Blocker(atom=atom,
- eapi=pkg.metadata["EAPI"], root=myroot)
+ eapi=pkg.metadata["EAPI"],
+ priority=self._priority(runtime=True),
+ root=myroot)
self._dynamic_config._blocker_parents.add(blocker, pkg)
except portage.exception.InvalidAtom as e:
depstr = " ".join(vardb.aux_get(pkg.cpv, dep_keys))
return eapi in _deprecated_eapis
def eapi_is_supported(eapi):
- eapi = str(eapi).strip()
+ if not isinstance(eapi, basestring):
+ # Only call str() when necessary since with python2 it
+ # can trigger UnicodeEncodeError if EAPI is corrupt.
+ eapi = str(eapi)
+ eapi = eapi.strip()
if _eapi_is_deprecated(eapi):
return True
if newmtime is not None:
os.utime(dest, (newmtime, newmtime))
else:
+ newmtime = sstat[stat.ST_MTIME]
if renamefailed:
- # If rename succeeded then this is not necessary, since
- # rename automatically preserves timestamps with complete
- # precision.
- if sstat[stat.ST_MTIME] == long(sstat.st_mtime):
- newmtime = sstat.st_mtime
- else:
- # Prevent mtime from rounding up to the next second.
- # Generate nanosecond resolution (9 decimal places) in
- # order to ensure that the floating point representation
- # is the highest value possible without rounding up.
- int_mtime = sstat[stat.ST_MTIME]
- mtime_str = "%i." % int_mtime
- nonzero_digits = 0
- decimal_places = 9
- for i in range(decimal_places):
- for digit in range(9, -1, -1):
- digit_str = str(digit)
- if int_mtime == long(float(mtime_str + digit_str)):
- break
- if digit > 0:
- nonzero_digits += 1
- mtime_str += digit_str
-
- if nonzero_digits > 0:
- newmtime = float(mtime_str)
- else:
- newmtime = int_mtime
-
+ # If rename succeeded then timestamps are automatically
+ # preserved with complete precision because the source
+ # and destination inode are the same. Otherwise, round
+ # down to the nearest whole second since python's float
+ # st_mtime cannot be used to preserve the st_mtim.tv_nsec
+ # field with complete precision. Note that we have to use
+ # stat_obj[stat.ST_MTIME] here because the float
+ # stat_obj.st_mtime rounds *up* sometimes.
os.utime(dest, (newmtime, newmtime))
- newmtime = sstat[stat.ST_MTIME]
except OSError:
# The utime can fail here with EPERM even though the move succeeded.
# Instead of failing, use stat to return the mtime if possible.