# Prefix additions
unset BPREFIX DEFAULT_PATH EPREFIX EROOT PORTAGE_GROUP PORTAGE_USER
+ # user config variables
+ unset DOC_SYMLINKS_DIR INSTALL_MASK PKG_INSTALL_MASK
+
set
export
)
self._blocker_uninstalls = digraph()
# Contains only Package -> Blocker edges
self._blocker_parents = digraph()
+ # Contains only irrelevant Package -> Blocker edges
+ self._irrelevant_blockers = digraph()
# Contains only unsolvable Package -> Blocker edges
self._unsolvable_blockers = digraph()
self._slot_collision_info = set()
blocker_atoms = None
blockers = None
if self.digraph.contains(pkg):
+ blockers = []
try:
- blockers = self._blocker_parents.child_nodes(pkg)
+ blockers.extend(
+ self._blocker_parents.child_nodes(pkg))
except KeyError:
- blockers = []
+ pass
+ try:
+ blockers.extend(
+ self._irrelevant_blockers.child_nodes(pkg))
+ except KeyError:
+ pass
if blockers is not None:
blockers = set("!" + blocker.atom \
for blocker in blockers)
self._blocker_parents.remove(blocker)
# Discard any parents that don't have any more blockers.
for pkg in parent_pkgs:
+ self._irrelevant_blockers.add(blocker, pkg)
if not self._blocker_parents.child_nodes(pkg):
self._blocker_parents.remove(pkg)
continue
# merged.
self._blocker_uninstalls.addnode(uninst_task, blocker)
if not unresolved_blocks and not depends_on_order:
+ self._irrelevant_blockers.add(blocker, parent)
self._blocker_parents.remove_edge(blocker, parent)
if not self._blocker_parents.parent_nodes(blocker):
self._blocker_parents.remove(blocker)
node.operation != "uninstall"]
# sys-apps/portage needs special treatment if ROOT="/"
- portage_python_dep = ">=dev-lang/python-2.4"
- portage_unslotted_deps = frozenset(
- ["app-shells/bash", "sys-apps/portage"])
- portage_node = self.mydbapi["/"].match_pkgs("sys-apps/portage")
- if portage_node:
- portage_node = portage_node[0]
+ running_root = "/"
+ from portage.const import PORTAGE_PACKAGE_ATOM
+ runtime_deps = InternalPackageSet(
+ initial_atoms=[PORTAGE_PACKAGE_ATOM])
+ running_portage = self.trees[running_root]["vartree"].dbapi.match_pkgs(
+ PORTAGE_PACKAGE_ATOM)
+ replacement_portage = self.mydbapi[running_root].match_pkgs(
+ PORTAGE_PACKAGE_ATOM)
+
+ if running_portage:
+ running_portage = running_portage[0]
else:
- portage_node = None
- if portage_node is not None and \
- (not mygraph.contains(portage_node) or \
- portage_node.operation == "nomerge"):
- portage_node = None
+ running_portage = None
+
+ if replacement_portage:
+ replacement_portage = replacement_portage[0]
+ else:
+ replacement_portage = None
+
+ if replacement_portage == running_portage:
+ replacement_portage = None
+
+ if running_portage is not None:
+ try:
+ portage_rdepend = self._select_atoms_highest_available(
+ running_root, running_portage.metadata["RDEPEND"],
+ myuse=running_portage.metadata["USE"].split(),
+ parent=running_portage, strict=False)
+ except portage.exception.InvalidDependString, e:
+ portage.writemsg("!!! Invalid RDEPEND in " + \
+ "'%svar/db/pkg/%s/RDEPEND': %s\n" % \
+ (running_root, running_portage.cpv, e), noiselevel=-1)
+ del e
+ portage_rdepend = []
+ runtime_deps.update(atom for atom in portage_rdepend \
+ if not atom.startswith("!"))
ignore_priority_soft_range = [None]
ignore_priority_soft_range.extend(
return True
if node not in mergeable_nodes:
return False
- if node == portage_node and mygraph.child_nodes(node,
+ if node == replacement_portage and \
+ mygraph.child_nodes(node,
ignore_priority=DepPriority.MEDIUM_SOFT):
# Make sure that portage always has all of it's
# RDEPENDs installed first.
if self.digraph.contains(inst_pkg):
continue
- if "/" == task.root:
+ if running_root == task.root:
# Never uninstall sys-apps/portage or it's essential
# dependencies, except through replacement.
- if task.cp in portage_unslotted_deps:
+ try:
+ runtime_dep_atoms = \
+ list(runtime_deps.iterAtomsForPackage(task))
+ except portage.exception.InvalidDependString, e:
+ portage.writemsg("!!! Invalid PROVIDE in " + \
+ "'%svar/db/pkg/%s/PROVIDE': %s\n" % \
+ (task.root, task.cpv, e), noiselevel=-1)
+ del e
continue
- # Don't uninstall python if it appears to be
- # the only suitable one installed.
- if task.cp == "dev-lang/python" and \
- portage.match_from_list(
- portage_python_dep, [task.cpv_slot]):
- vardb = root_config.trees["vartree"].dbapi
+ # Don't uninstall a runtime dep if it appears
+ # to be the only suitable one installed.
+ skip = False
+ vardb = root_config.trees["vartree"].dbapi
+ for atom in runtime_dep_atoms:
other_version = None
- for pkg in vardb.match_pkgs(portage_python_dep):
+ for pkg in vardb.match_pkgs(atom):
if pkg.cpv == task.cpv and \
pkg.metadata["COUNTER"] == \
task.metadata["COUNTER"]:
other_version = pkg
break
if other_version is None:
- continue
+ skip = True
+ break
+ if skip:
+ continue
# For packages in the system set, don't take
# any chances. If the conflict can't be resolved
"system"].iterAtomsForPackage(task):
skip = True
break
- except portage.exception.InvalidDependString:
+ except portage.exception.InvalidDependString, e:
+ portage.writemsg("!!! Invalid PROVIDE in " + \
+ "'%svar/db/pkg/%s/PROVIDE': %s\n" % \
+ (task.root, task.cpv, e), noiselevel=-1)
+ del e
skip = True
if skip:
continue
if not satisfied:
skip = True
break
- except portage.exception.InvalidDependString:
+ except portage.exception.InvalidDependString, e:
+ portage.writemsg("!!! Invalid PROVIDE in " + \
+ "'%svar/db/pkg/%s/PROVIDE': %s\n" % \
+ (task.root, task.cpv, e), noiselevel=-1)
+ del e
skip = True
if skip:
continue
del mtimedb[k]
continue
favorites = resume_data.get("favorites")
- if not isinstance(resume_opts, list):
+ if not isinstance(favorites, list):
del mtimedb[k]
continue
retval = mergetask.merge(pkglist, favorites, mtimedb)
merge_count = mergetask.curval
- if retval == os.EX_OK and not (pretend or fetchonly):
- mtimedb.pop("resume", None)
+ if retval == os.EX_OK and not (buildpkgonly or fetchonly or pretend):
if "yes" == settings.get("AUTOCLEAN"):
portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
unmerge(trees[settings["ROOT"]]["root_config"],
"PORTAGE_GROUP", "PORTAGE_USER",
]
+ # user config variables
+ _environ_whitelist += [
+ "DOC_SYMLINKS_DIR", "INSTALL_MASK", "PKG_INSTALL_MASK"
+ ]
+
_environ_whitelist += [
"A", "AA", "CATEGORY", "P", "PF", "PN", "PR", "PV", "PVR"
]
PORTAGE_BASE_PATH = PORTAGE_BASE
PORTAGE_BIN_PATH = PORTAGE_BASE_PATH+"/bin"
PORTAGE_PYM_PATH = PORTAGE_BASE_PATH+"/pym"
+PORTAGE_PACKAGE_ATOM = "sys-apps/portage"
NEWS_LIB_PATH = EPREFIX+"/var/lib/gentoo"
PROFILE_PATH = EPREFIX+"/etc/make.profile"
LOCALE_DATA_PATH = PORTAGE_BASE_PATH+"/locale"
"CONFIG_PROTECT_MASK", "CONFIG_PROTECT",
"PRELINK_PATH", "PRELINK_PATH_MASK", "PROFILE_ONLY_VARIABLES"]
EBUILD_PHASES = ["setup", "unpack", "compile", "test", "install",
- "preinst", "postinst", "prerm", "postrm", "other"]
+ "package", "preinst", "postinst","prerm", "postrm",
+ "other"]
EAPI = 1
from portage.dbapi import dbapi
from portage.dep import dep_getslot, use_reduce, paren_reduce, isvalidatom, \
isjustname, dep_getkey, match_from_list
-from portage.exception import InvalidPackageName, InvalidAtom, \
+from portage.exception import InvalidAtom, InvalidData, InvalidPackageName, \
FileNotFound, PermissionDenied, UnsupportedAPIException
from portage.locks import lockdir, unlockdir
from portage.output import bold, red, green
self._obj_properties = {}
self._defpath = getlibpaths()
- def rebuild(self):
+ def rebuild(self, include_file=None):
libs = {}
obj_properties = {}
lines = []
for cpv in self._dbapi.cpv_all():
lines += grabfile(self._dbapi.getpath(cpv, filename="NEEDED.ELF.2"))
-
+
+ if include_file:
+ lines += grabfile(include_file)
+
# have to call scanelf for preserved libs here as they aren't
# registered in NEEDED.ELF.2 files
if self._dbapi.plib_registry and self._dbapi.plib_registry.getPreservedLibs():
def findProviders(self, obj):
if not self._libs:
self.rebuild()
- obj = os.path.realpath(obj)
rValue = {}
if obj not in self._obj_properties:
- raise KeyError("%s not in object list" % obj)
+ obj = os.path.realpath(obj)
+ if obj not in self._obj_properties:
+ raise KeyError("%s not in object list" % obj)
arch, needed, path, soname = self._obj_properties[obj]
path.extend(self._defpath)
path = [os.path.realpath(x) for x in path]
def findConsumers(self, obj):
if not self._libs:
self.rebuild()
- obj = os.path.realpath(obj)
+ if obj not in self._obj_properties:
+ obj = os.path.realpath(obj)
+ if obj not in self._obj_properties:
+ raise KeyError("%s not in object list" % obj)
rValue = set()
for soname in self._libs:
for arch in self._libs[soname]:
return rValue
class vardbapi(dbapi):
+
+ _excluded_dirs = ["CVS", "lost+found"]
+ _excluded_dirs = [re.escape(x) for x in _excluded_dirs]
+ _excluded_dirs = re.compile(r'^(\..*|-MERGING-.*|' + \
+ "|".join(_excluded_dirs) + r')$')
+
def __init__(self, root, categories=None, settings=None, vartree=None):
"""
The categories parameter is unused since the dbapi class
returnme = []
for x in dir_list:
- if x.startswith("."):
- continue
- if x[0] == '-':
- #writemsg(red("INCOMPLETE MERGE:")+str(x[len("-MERGING-"):])+"\n")
+ if self._excluded_dirs.match(x) is not None:
continue
ps = pkgsplit(x)
if not ps:
returnme = []
basepath = os.path.join(self.root, VDB_PATH) + os.path.sep
for x in listdir(basepath, EmptyOnError=1, ignorecvs=1, dirsonly=1):
+ if self._excluded_dirs.match(x) is not None:
+ continue
if not self._category_re.match(x):
continue
- for y in listdir(basepath + x, EmptyOnError=1):
- if y.startswith("."):
+ for y in listdir(basepath + x, EmptyOnError=1, dirsonly=1):
+ if self._excluded_dirs.match(y) is not None:
continue
subpath = x + "/" + y
# -MERGING- should never be a cpv, nor should files.
- if os.path.isdir(basepath + subpath) and (pkgsplit(y) is not None):
- returnme += [subpath]
+ try:
+ if catpkgsplit(subpath) is None:
+ self.invalidentry(os.path.join(self.root, subpath))
+ continue
+ except portage.exception.InvalidData:
+ self.invalidentry(os.path.join(self.root, subpath))
+ continue
+ returnme.append(subpath)
return returnme
def cp_all(self, use_cache=1):
for y in mylist:
if y[0] == '*':
y = y[1:]
- mysplit = catpkgsplit(y)
+ try:
+ mysplit = catpkgsplit(y)
+ except portage.exception.InvalidData:
+ self.invalidentry(self.getpath(y))
+ continue
if not mysplit:
self.invalidentry(self.getpath(y))
continue
return False
- def _preserve_libs(self, srcroot, destroot, mycontents, counter):
+ def _preserve_libs(self, srcroot, destroot, mycontents, counter, inforoot):
# read global reverse NEEDED map
linkmap = self.vartree.dbapi.linkmap
- linkmap.rebuild()
+ linkmap.rebuild(include_file=os.path.join(inforoot, "NEEDED.ELF.2"))
liblist = linkmap.listLibraryObjects()
# get list of libraries from old package instance
old_libs = set(old_contents).intersection(liblist)
# get list of libraries from new package instance
- mylibs = set(mycontents).intersection(liblist)
-
+ mylibs = set([os.path.join(os.sep, x) for x in mycontents]).intersection(liblist)
+
# check which libs are present in the old, but not the new package instance
candidates = old_libs.difference(mylibs)
+
for x in old_contents:
- if os.path.islink(x) and os.path.realpath(x) in candidates:
+ if os.path.islink(x) and os.path.realpath(x) in candidates and x not in mycontents:
candidates.add(x)
# ignore any libs that are only internally used by the package
for c in linkmap.findConsumers(lib):
localkeep = True
providers = linkmap.findProviders(c)
+
for soname in providers:
if lib in providers[soname]:
for p in providers[soname]:
# Preserve old libs if they are still in use
if slot_matches and "preserve-libs" in self.settings.features:
- self._preserve_libs(srcroot, destroot, myfilelist+mylinklist, counter)
+ self._preserve_libs(srcroot, destroot, myfilelist+mylinklist, counter, inforoot)
# check for package collisions
collisions = self._collision_protect(srcroot, destroot, others_in_slot,