# and will automaticly add a command by the same name as the function!
#
-
def has_version(argv):
"""<root> <category/package>
Return code 0 if it's available, 1 otherwise.
for arg in arvg[1:]:
print portage.db[argv[0]]["porttree"].dbapi.getRepositoryPath(argv[1])
+def list_preserved_libs(argv):
+ """<root>
+ Print a list of libraries preserved during a package update in the form
+ package: path. Returns 0 if no preserved libraries could be found,
+ 1 otherwise.
+ """
+
+ if len(argv) != 1:
+ print "ERROR: wrong number of arguments"
+ sys.exit(2)
+ mylibs = portage.db[argv[0]]["vartree"].dbapi.plib_registry.getPreservedLibs()
+ rValue = 0
+ for cpv in mylibs.keys():
+ for path in mylibs[cpv]:
+ print "%s: %s" % (cpv, path)
+ rValue = 1
+ return rValue
+
#-----------------------------------------------------------------------------
#
# DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED!
# Show our commands -- we do this by scanning the functions in this
# file, and formatting each functions documentation.
#
- for name in globals().keys():
- # Drop python stuff, modules, and our own support functions.
- if (name in ("usage", "__doc__", "__name__", "main", "os", "portage", "sys", "__builtins__", "types", "string","exithandler")):
- continue
+ commands = [x for x in globals().keys() if x not in \
+ ("usage", "__doc__", "__name__", "main", "os", "portage", \
+ "sys", "__builtins__", "types", "string","exithandler")]
+ commands.sort()
+ for name in commands:
# Drop non-functions
obj = globals()[name]
if (type(obj) != types.FunctionType):
import portage
del os.environ["PORTAGE_LEGACY_GLOBALS"]
from portage import digraph, portdbapi
-from portage.const import NEWS_LIB_PATH, CACHE_PATH
+from portage.const import NEWS_LIB_PATH, CACHE_PATH, PRIVATE_PATH
import emerge.help
import portage.xpak, commands, errno, re, socket, time, types
if not circular_blocks:
circular_blocks = True
blocker_deps = myblockers.leaf_nodes()
- if blocker_deps:
- selected_nodes = [blocker_deps.pop()]
+ while blocker_deps:
+ # Some of these nodes might have already been selected
+ # by the normal node selection process after the
+ # circular_blocks flag has been set. Therefore, we
+ # have to verify that they're still in the graph so
+ # that they're not selected more than once.
+ node = blocker_deps.pop()
+ if mygraph.contains(node):
+ selected_nodes = [node]
+ break
if not selected_nodes:
# No leaf nodes are available, so we have a circular
print " "+green("*")+" Processed",icount,"info files."
-def display_news_notification(settings):
- target_root = settings["ROOT"]
+def display_news_notification(trees):
+ for target_root in trees:
+ if len(trees) > 1 and target_root != "/":
+ break
+ settings = trees[target_root]["vartree"].settings
+ portdb = trees[target_root]["porttree"].dbapi
+ vardb = trees[target_root]["vartree"].dbapi
NEWS_PATH = os.path.join("metadata", "news")
UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news")
- porttree = portdbapi(porttree_root=settings["PORTDIR"], mysettings=settings)
newsReaderDisplay = False
- for repo in porttree.getRepositories():
- unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
+ for repo in portdb.getRepositories():
+ unreadItems = checkUpdatedNewsItems(
+ portdb, vardb, NEWS_PATH, UNREAD_PATH, repo)
if unreadItems:
if not newsReaderDisplay:
newsReaderDisplay = True
print "Use " + colorize("GOOD", "eselect news") + " to read news items."
print
-def post_emerge(settings, mtimedb, retval):
+def post_emerge(trees, mtimedb, retval):
"""
Misc. things to run at the end of a merge session.
Commit mtimeDB
Display preserved libs warnings
Exit Emerge
-
- @param settings: Configuration settings (typically portage.settings)
- @type settings: portage.config()
+
+ @param trees: A dictionary mapping each ROOT to it's package databases
+ @type trees: dict
@param mtimedb: The mtimeDB to store data needed across merge invocations
@type mtimedb: MtimeDB class instance
@param retval: Emerge's return value
@returns:
1. Calls sys.exit(retval)
"""
- target_root = settings["ROOT"]
+ for target_root in trees:
+ if len(trees) > 1 and target_root != "/":
+ break
+ vardbapi = trees[target_root]["vartree"].dbapi
+ settings = vardbapi.settings
info_mtimes = mtimedb["info"]
# Load the most current variables from ${ROOT}/etc/profile.env
chk_updated_info_files(normalize_path(target_root + EPREFIX), infodirs, info_mtimes, retval)
chk_updated_cfg_files(normalize_path(target_root + EPREFIX), config_protect)
- display_news_notification(settings)
+ display_news_notification(trees)
- from portage.dbapi.vartree import PreservedLibsRegistry
- plib_registry = PreservedLibsRegistry(os.path.join(target_root, CACHE_PATH, "preserved_libs_registry"))
- if plib_registry.hasEntries():
+ if vardbapi.plib_registry.hasEntries():
print colorize("WARN", "!!!") + " existing preserved libs:"
- plibdata = plib_registry.getPreservedLibs()
+ plibdata = vardbapi.plib_registry.getPreservedLibs()
for cpv in plibdata.keys():
print colorize("WARN", ">>>") + " package: %s" % cpv
for f in plibdata[cpv]:
#print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
-def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
+def checkUpdatedNewsItems(portdb, vardb, NEWS_PATH, UNREAD_PATH, repo_id):
"""
Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
Returns the number of unread (yet relevent) items.
- @param root:
- @type root:
+ @param portdb: a portage tree database
+ @type portdb: pordbapi
+ @param vardb: an installed package database
+ @type vardb: vardbapi
@param NEWS_PATH:
@type NEWS_PATH:
@param UNREAD_PATH:
"""
from portage.news import NewsManager
- manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
+ manager = NewsManager(portdb, vardb, NEWS_PATH, UNREAD_PATH)
return manager.getUnreadItems( repo_id, update=True )
def is_valid_package_atom(x):
print red(" * ")+"To update portage, run 'emerge portage'."
print
- display_news_notification(settings)
+ display_news_notification(trees)
def action_metadata(settings, portdb, myopts):
portage.writemsg_stdout("\n>>> Updating Portage cache: ")
if "--ask" in myopts:
myopts["--pretend"] = True
del myopts["--ask"]
- print ("%s access would be required... " + \
+ print ("%s access is required... " + \
"adding --pretend to options.\n") % access_desc
if portage.secpass < 1 and not need_superuser:
portage_group_warning()
else:
- sys.stderr.write(("emerge: %s access would be " + \
+ sys.stderr.write(("emerge: %s access is " + \
"required.\n\n") % access_desc)
if portage.secpass < 1 and not need_superuser:
portage_group_warning()
if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
mtimedb["ldpath"]):
if "--pretend" not in myopts:
- post_emerge(settings, mtimedb, 0)
+ post_emerge(trees, mtimedb, os.EX_OK)
elif "depclean"==myaction:
validate_ebuild_environment(trees)
action_depclean(settings, trees, mtimedb["ldpath"],
myopts, spinner)
if "--pretend" not in myopts:
- post_emerge(settings, mtimedb, 0)
+ post_emerge(trees, mtimedb, os.EX_OK)
# "update", "system", or just process files:
else:
validate_ebuild_environment(trees)
if "--pretend" not in myopts:
- display_news_notification(settings)
+ display_news_notification(trees)
action_build(settings, trees, mtimedb,
myopts, myaction, myfiles, spinner)
if "--pretend" not in myopts:
- post_emerge(settings, mtimedb, 0)
+ post_emerge(trees, mtimedb, os.EX_OK)
else:
- display_news_notification(settings)
+ display_news_notification(trees)
if __name__ == "__main__":
retval = emerge_main()
self._aux_cache_filename = os.path.join(self.root,
CACHE_PATH.lstrip(os.path.sep), "vdb_metadata.pickle")
- self.libmap = LibraryPackageMap(os.path.join(self.root, CACHE_PATH, "library_consumers"), self)
- self.plib_registry = PreservedLibsRegistry(os.path.join(self.root, CACHE_PATH, "preserved_libs_registry"))
+ self.libmap = LibraryPackageMap(os.path.join(self.root, CACHE_PATH.lstrip(os.sep), "library_consumers"), self)
+ self.plib_registry = PreservedLibsRegistry(os.path.join(self.root, PRIVATE_PATH, "preserved_libs_registry"))
def getpath(self, mykey, filename=None):
rValue = os.path.join(self.root, VDB_PATH, mykey)
except (OSError, AttributeError):
pass
islink = lstatobj is not None and stat.S_ISLNK(lstatobj.st_mode)
- if not unmerge_orphans and statobj is None:
- if not islink:
- #we skip this if we're dealing with a symlink
- #because os.stat() will operate on the
- #link target rather than the link itself.
- writemsg_stdout("--- !found " + str(pkgfiles[objkey][0]) + " %s\n" % obj)
+ if lstatobj is None:
+ writemsg_stdout("--- !found %s %s\n" % (file_type, obj))
continue
# next line includes a tweak to protect modules from being unmerged,
# but we don't protect modules from being overwritten if they are
writemsg_stdout("--- cfgpro %s %s\n" % (pkgfiles[objkey][0], obj))
continue
+ # Don't unlink symlinks to directories here since that can
+ # remove /lib and /usr/lib symlinks.
if unmerge_orphans and \
lstatobj and not stat.S_ISDIR(lstatobj.st_mode) and \
+ not (islink and statobj and stat.S_ISDIR(statobj.st_mode)) and \
not self.isprotected(obj):
try:
# Remove permissions to ensure that any hardlinks to
# suid/sgid files are rendered harmless.
- if statobj:
+ if statobj and not islink:
os.chmod(obj, 0)
os.unlink(obj)
except EnvironmentError, e:
if not islink:
writemsg_stdout("--- !sym %s %s\n" % ("sym", obj))
continue
+ # Go ahead and unlink symlinks to directories here when
+ # they're actually recorded as symlinks in the contents.
+ # Normally, symlinks such as /lib -> lib64 are not recorded
+ # as symlinks in the contents of a package. If a package
+ # installs something into ${D}/lib/, it is recorded in the
+ # contents as a directory even if it happens to correspond
+ # to a symlink when it's merged to the live filesystem.
try:
os.unlink(obj)
writemsg_stdout("<<< %s %s\n" % ("sym", obj))
i = i + 1
if i % 1000 == 0:
print str(i)+" files checked ..."
+ dest_path = normalize_path(
+ os.path.join(destroot, f.lstrip(os.path.sep)))
+ try:
+ dest_lstat = os.lstat(dest_path)
+ except EnvironmentError, e:
+ if e.errno != errno.ENOENT:
+ raise
+ del e
+ continue
if f[0] != "/":
f="/"+f
isowned = False
# $Id$
from portage.const import INCREMENTALS, PROFILE_PATH, NEWS_LIB_PATH
-from portage import config, vartree, vardbapi, portdbapi
from portage.util import ensure_dirs, apply_permissions
from portage.data import portage_gid
from portage.locks import lockfile, unlockfile, lockdir, unlockdir
TIMESTAMP_FILE = "news-timestamp"
- def __init__(self, root, NEWS_PATH, UNREAD_PATH, LANGUAGE_ID='en'):
+ def __init__(self, portdb, vardb, NEWS_PATH, UNREAD_PATH, LANGUAGE_ID='en'):
self.NEWS_PATH = NEWS_PATH
self.UNREAD_PATH = UNREAD_PATH
- self.TIMESTAMP_PATH = os.path.join(root, NEWS_LIB_PATH, NewsManager.TIMESTAMP_FILE)
- self.target_root = root
+ self.TIMESTAMP_PATH = os.path.join(vardb.root,
+ NEWS_LIB_PATH, NewsManager.TIMESTAMP_FILE)
+ self.target_root = vardb.root
self.LANGUAGE_ID = LANGUAGE_ID
- self.config = config(config_root = os.environ.get("PORTAGE_CONFIGROOT", "/"),
- target_root = root, config_incrementals = INCREMENTALS)
- self.vdb = vardbapi(settings = self.config, root = root,
- vartree = vartree(root = root, settings = self.config))
- self.portdb = portdbapi(porttree_root = self.config["PORTDIR"], mysettings = self.config)
+ self.config = vardb.settings
+ self.vdb = vardb
+ self.portdb = portdb
# Ensure that the unread path exists and is writable.
dirmode = 02070