LOCAL_EXTRA_ECONF="--libdir=${CONF_LIBDIR_RESULT} ${LOCAL_EXTRA_ECONF}"
fi
- local TMP_CONFCACHE_DIR CONFCACHE_ARG
- if hasq confcache $FEATURES && ! hasq confcache $RESTRICT; then
- CONFCACHE="$(type -P confcache)"
- if [ -z "${CONFCACHE}" ]; then
- ewarn "disabling confcache, binary cannot be found"
- else
- CONFCACHE="${CONFCACHE/ /\ }"
- TMP_CONFCACHE_DIR="${CONFCACHE:+${CONFCACHE_DIR:-${PORTAGE_TMPDIR}/confcache}}"
- TMP_CONFCACHE_DIR="${TMP_CONFCACHE_DIR/ /\ }"
- CONFCACHE_ARG="--confcache-dir"
- local s
- if [ -n "$CCACHE_DIR" ]; then
- s="$CCACHE_DIR"
- fi
- if [ -n "$DISTCC_DIR" ]; then
- s="${s:+${s}:}$DISTCC_DIR"
- fi
- if [ -n "$s" ]; then
- CONFCACHE_ARG="--confcache-ignore $s $CONFCACHE_ARG"
- fi
- fi
- else
- CONFCACHE=
- fi
-
- vecho ${CONFCACHE} ${CONFCACHE_ARG} ${TMP_CONFCACHE_DIR} "${ECONF_SOURCE}/configure" \
+ vecho "${ECONF_SOURCE}/configure" \
--prefix="${EPREFIX}"/usr \
--host=${CHOST} \
--mandir="${EPREFIX}"/usr/share/man \
"$@" \
${LOCAL_EXTRA_ECONF}
- if ! ${CONFCACHE} ${CONFCACHE_ARG} ${TMP_CONFCACHE_DIR} "${ECONF_SOURCE}/configure" \
+ if ! "${ECONF_SOURCE}/configure" \
--prefix="${EPREFIX}"/usr \
--host=${CHOST} \
--mandir="${EPREFIX}"/usr/share/man \
# /etc/make.globals here because emake is only called from an
# ebuild.
+[[ $PORTAGE_QUIET = 1 ]] || echo ${MAKE:-make} ${MAKEOPTS} ${EXTRA_EMAKE} "$@"
+
exec ${MAKE:-make} ${MAKEOPTS} ${EXTRA_EMAKE} "$@"
(( COLS > 0 )) || (( COLS = 80 ))
COLS=$((${COLS} - 8)) # width of [ ok ] == 7
# Adjust COLS so that eend works properly on a standard BSD console.
- [ "${TERM}" = "cons25" ] && COLS=$((${COLS} - 1))
+ [[ $TERM = cons25 || $TERM = dumb ]] && ((COLS--))
# Now, ${ENDCOL} will move us to the end of the
# column; irregardless of character width
PORTAGE_INST_UID PORTAGE_LOG_FILE PORTAGE_MASTER_PID \
PORTAGE_QUIET \
PORTAGE_REPO_NAME PORTAGE_RESTRICT PORTAGE_UPDATE_ENV \
- PORTAGE_WORKDIR_MODE PORTDIR \
+ PORTAGE_VERBOSE PORTAGE_WORKDIR_MODE PORTDIR \
PORTDIR_OVERLAY ${!PORTAGE_SANDBOX_*} PREROOTPATH \
PROFILE_PATHS PWORKDIR QA_INTERCEPTORS \
RC_DEFAULT_INDENT RC_DOT_PATTERN RC_ENDCOL \
# $Id$
import sys, os
+import portage.exception
# for an explanation on this logic, see pym/_emerge/__init__.py
import os
#print "checking:",mykey
try:
mylist=portage.db["/"]["vartree"].dbapi.match(mykey)
- except KeyError:
+ except (portage.exception.InvalidAtom, KeyError):
if "--debug" in sys.argv:
print "* ignoring broken log entry for %s (likely injected)" % mykey
except ValueError, e:
modified_changelogs = set()
mychanged = []
mynew = []
+myremoved = []
+
if vcs == "cvs":
mycvstree = cvstree.getentries("./", recursive=1)
mychanged = cvstree.findchanged(mycvstree, recursive=1, basedir="./")
portdb.mysettings = dep_settings
portdb.xcache = xcache
# for package.use.mask support inside dep_check
- dep_settings.setcpv("/".join((catdir, y)))
+ dep_settings.setcpv(pkg)
dep_settings["ACCEPT_KEYWORDS"] = " ".join(groups)
# just in case, prevent config.reset() from nuking these.
dep_settings.backup_changes("ACCEPT_KEYWORDS")
unameout += platform.processor()
else:
unameout += platform.machine()
- commitmessage+="\n(Portage version: "+str(portage_version)+"/"+vcs+"/"+unameout
+ commitmessage += "\n(Portage version: %s/%s/%s" % \
+ (portage_version, vcs, unameout)
if options.force:
commitmessage += ", RepoMan options: --force"
commitmessage += ")"
import portage
-from portage import digraph, portdbapi
-from portage.const import NEWS_LIB_PATH, CACHE_PATH, PRIVATE_PATH, USER_CONFIG_PATH, GLOBAL_CONFIG_PATH
+from portage import digraph
+from portage.const import NEWS_LIB_PATH
import _emerge.help
import portage.xpak, commands, errno, re, socket, time, types
from portage.output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
- havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
+ nc_len, red, teal, turquoise, xtermTitle, \
xtermTitleReset, yellow
from portage.output import create_color_func
good = create_color_func("GOOD")
candidate_catpkgs=[]
global_unmerge=0
xterm_titles = "notitles" not in settings.features
-
+ out = portage.output.EOutput()
pkg_cache = {}
db_keys = list(vartree.dbapi._aux_cache_keys)
# It could have been uninstalled
# by a concurrent process.
continue
+
+ if unmerge_action != "clean" and \
+ root_config.root == "/" and \
+ portage.match_from_list(
+ portage.const.PORTAGE_PACKAGE_ATOM, [pkg]):
+ msg = ("Not unmerging package %s since there is no valid " + \
+ "reason for portage to unmerge itself.") % (pkg.cpv,)
+ for line in textwrap.wrap(msg, 75):
+ out.eerror(line)
+ # adjust pkgmap so the display output is correct
+ pkgmap[cp]["selected"].remove(cpv)
+ all_selected.remove(cpv)
+ pkgmap[cp]["protected"].add(cpv)
+ continue
+
parents = []
for s in installed_sets:
# skip sets that the user requested to unmerge, and skip world
print " %s\n" % ", ".join(parents)
# adjust pkgmap so the display output is correct
pkgmap[cp]["selected"].remove(cpv)
+ all_selected.remove(cpv)
pkgmap[cp]["protected"].add(cpv)
del installed_sets
+ numselected = len(all_selected)
+ if not numselected:
+ writemsg_level(
+ "\n>>> No packages selected for removal by " + \
+ unmerge_action + "\n")
+ return 0
+
# Unmerge order only matters in some cases
if not ordered:
unordered = {}
portdb = trees[settings["ROOT"]]["porttree"].dbapi
root_config = trees[settings["ROOT"]]["root_config"]
- mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
+ mybestpv = portdb.xmatch("bestmatch-visible",
+ portage.const.PORTAGE_PACKAGE_ATOM)
mypvs = portage.best(
- trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
+ trees[settings["ROOT"]]["vartree"].dbapi.match(
+ portage.const.PORTAGE_PACKAGE_ATOM))
chk_updated_cfg_files(EPREFIX, settings.get("CONFIG_PROTECT","").split())
if defaults != self.configdict["defaults"].get("USE",""):
self.configdict["defaults"]["USE"] = defaults
has_changed = True
- useforce = []
- pos = 0
- for i in xrange(len(self.profiles)):
- cpdict = self.puseforce_list[i].get(cp, None)
- if cpdict:
- keys = cpdict.keys()
- while keys:
- best_match = best_match_to_list(cpv_slot, keys)
- if best_match:
- keys.remove(best_match)
- useforce.insert(pos, cpdict[best_match])
- else:
- break
- del keys
- if self.useforce_list[i]:
- useforce.insert(pos, self.useforce_list[i])
- pos = len(useforce)
- useforce = set(stack_lists(useforce, incremental=True))
+
+ useforce = self._getUseForce(cpv_slot)
if useforce != self.useforce:
self.useforce = useforce
has_changed = True
- usemask = []
- pos = 0
- for i in xrange(len(self.profiles)):
- cpdict = self.pusemask_list[i].get(cp, None)
- if cpdict:
- keys = cpdict.keys()
- while keys:
- best_match = best_match_to_list(cpv_slot, keys)
- if best_match:
- keys.remove(best_match)
- usemask.insert(pos, cpdict[best_match])
- else:
- break
- del keys
- if self.usemask_list[i]:
- usemask.insert(pos, self.usemask_list[i])
- pos = len(usemask)
- usemask = set(stack_lists(usemask, incremental=True))
+
+ usemask = self._getUseMask(cpv_slot)
if usemask != self.usemask:
self.usemask = usemask
has_changed = True
return iuse_implicit
+ def _getUseMask(self, pkg):
+ cp = getattr(pkg, "cp", None)
+ if cp is None:
+ cp = dep_getkey(pkg)
+ usemask = []
+ pos = 0
+ for i in xrange(len(self.profiles)):
+ cpdict = self.pusemask_list[i].get(cp, None)
+ if cpdict:
+ keys = cpdict.keys()
+ while keys:
+ best_match = best_match_to_list(pkg, keys)
+ if best_match:
+ keys.remove(best_match)
+ usemask.insert(pos, cpdict[best_match])
+ else:
+ break
+ del keys
+ if self.usemask_list[i]:
+ usemask.insert(pos, self.usemask_list[i])
+ pos = len(usemask)
+ return set(stack_lists(usemask, incremental=True))
+
+ def _getUseForce(self, pkg):
+ cp = getattr(pkg, "cp", None)
+ if cp is None:
+ cp = dep_getkey(pkg)
+ useforce = []
+ pos = 0
+ for i in xrange(len(self.profiles)):
+ cpdict = self.puseforce_list[i].get(cp, None)
+ if cpdict:
+ keys = cpdict.keys()
+ while keys:
+ best_match = best_match_to_list(pkg, keys)
+ if best_match:
+ keys.remove(best_match)
+ useforce.insert(pos, cpdict[best_match])
+ else:
+ break
+ del keys
+ if self.useforce_list[i]:
+ useforce.insert(pos, self.useforce_list[i])
+ pos = len(useforce)
+ return set(stack_lists(useforce, incremental=True))
+
def _getMaskAtom(self, cpv, metadata):
"""
Take a package and return a matching package.mask atom, or None if no
"basedir_var":"CCACHE_DIR",
"default_dir":os.path.join(mysettings["PORTAGE_TMPDIR"], "ccache"),
"always_recurse":False},
- "confcache":{
- "basedir_var":"CONFCACHE_DIR",
- "default_dir":os.path.join(mysettings["PORTAGE_TMPDIR"], "confcache"),
- "always_recurse":False},
"distcc":{
"basedir_var":"DISTCC_DIR",
"default_dir":os.path.join(mysettings["BUILD_PREFIX"], ".distcc"),
return newsplit
def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
- trees=None, **kwargs):
+ trees=None, use_mask=None, use_force=None, **kwargs):
"""Recursively expand new-style virtuals so as to collapse one or more
levels of indirection. In dep_zapdeps, new-style virtuals will be assigned
zero cost regardless of whether or not they are currently installed. Virtual
raise portage.exception.ParseError(
"invalid atom: '%s'" % x)
- # Repoman only checks IUSE for USE deps, so there's
- # no need to evaluate conditionals.
+ if repoman and x.use and x.use.conditional:
+ evaluated_atom = portage.dep.remove_slot(x)
+ if x.slot:
+ evaluated_atom += ":%s" % x.slot
+ evaluated_atom += str(x.use._eval_qa_conditionals(
+ use_mask, use_force))
+ x = portage.dep.Atom(evaluated_atom)
+
if not repoman and \
myuse is not None and isinstance(x, portage.dep.Atom) and x.use:
if x.use.conditional:
# collapse one or more levels of indirection.
try:
mysplit = _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings,
- use=use, mode=mode, myuse=myuse, use_cache=use_cache,
+ use=use, mode=mode, myuse=myuse,
+ use_force=useforce, use_mask=mymasks, use_cache=use_cache,
use_binaries=use_binaries, myroot=myroot, trees=trees)
except portage.exception.ParseError, e:
return [0, str(e)]
# Distributed under the terms of the GNU General Public License v2
# $Id$
+__all__ = ["dbapi"]
+
import os
import re
-from portage.dep import Atom, dep_getslot, dep_getkey, \
- dep_getusedeps, match_from_list
+from portage.dep import match_from_list
from portage.locks import unlockfile
from portage.output import red
from portage.util import writemsg
from portage import auxdbkeys, dep_expand
-from portage.versions import catpkgsplit, catsplit, pkgcmp
+from portage.versions import catpkgsplit, pkgcmp
class dbapi(object):
self._iuse_implicit = self.settings._get_implicit_iuse()
for cpv in cpv_iter:
try:
- iuse, use = self.aux_get(cpv, ["IUSE", "USE"])
+ iuse, slot, use = self.aux_get(cpv, ["IUSE", "SLOT", "USE"])
except KeyError:
continue
use = use.split()
continue
if atom.use.disabled.intersection(use):
continue
+ else:
+ # Check masked and forced flags for repoman.
+ mysettings = getattr(self, "mysettings", None)
+ if mysettings is not None and not mysettings.local_config:
+
+ pkg = "%s:%s" % (cpv, slot)
+ usemask = mysettings._getUseMask(pkg)
+ if usemask.intersection(atom.use.enabled):
+ continue
+
+ useforce = mysettings._getUseForce(pkg).difference(usemask)
+ if useforce.intersection(atom.use.disabled):
+ continue
+
yield cpv
def invalidentry(self, mypath):
# Distributed under the terms of the GNU General Public License v2
# $Id$
+__all__ = ["bindbapi", "binarytree"]
+
from portage.cache.mappings import slot_dict_class
from portage.dep import isvalidatom, isjustname, dep_getkey, match_from_list
from portage.dbapi.virtual import fakedbapi
-from portage.exception import InvalidPackageName, InvalidAtom, \
+from portage.exception import InvalidPackageName, \
PermissionDenied, PortageException
from portage.output import green, EOutput
from portage.util import ensure_dirs, normalize_path, writemsg, writemsg_stdout
from portage.checksum import perform_md5
from portage.const import CACHE_PATH, CONFIG_MEMORY_FILE, \
- PRIVATE_PATH, VDB_PATH, EPREFIX, EPREFIX_LSTRIP
-from portage.data import portage_gid, portage_uid, secpass, ostype
+ PORTAGE_PACKAGE_ATOM, PRIVATE_PATH, VDB_PATH, EPREFIX, EPREFIX_LSTRIP
+from portage.data import portage_gid, portage_uid, secpass
from portage.dbapi import dbapi
from portage.dep import use_reduce, paren_reduce, isvalidatom, \
- isjustname, dep_getkey
+ isjustname, dep_getkey, match_from_list
from portage.exception import InvalidData, InvalidPackageName, \
FileNotFound, PermissionDenied, UnsupportedAPIException
from portage.locks import lockdir, unlockdir
collision_ignore = set([normalize_path(myignore) for myignore in \
shlex.split(self.settings.get("COLLISION_IGNORE", ""))])
+ # For collisions with preserved libraries, the current package
+ # will assume ownership and the libraries will be unregistered.
+ plib_dict = self.vartree.dbapi.plib_registry.getPreservedLibs()
+ plib_cpv_map = {}
+ plib_paths = set()
+ for cpv, paths in plib_dict.iteritems():
+ plib_paths.update(paths)
+ for f in paths:
+ plib_cpv_map[f] = cpv
+ plib_inodes = self._lstat_inode_map(plib_paths)
+ plib_collisions = {}
+
showMessage = self._display_merge
scheduler = self._scheduler
stopmerge = False
raise
if f[0] != "/":
f="/"+f
+
+ plibs = plib_inodes.get((dest_lstat.st_dev, dest_lstat.st_ino))
+ if plibs:
+ for path in plibs:
+ cpv = plib_cpv_map[path]
+ paths = plib_collisions.get(cpv)
+ if paths is None:
+ paths = set()
+ plib_collisions[cpv] = paths
+ paths.add(path)
+ # The current package will assume ownership and the
+ # libraries will be unregistered, so exclude this
+ # path from the normal collisions.
+ continue
+
isowned = False
full_path = os.path.join(destroot, f.lstrip(os.path.sep))
- for ver in [self] + mypkglist:
- if (ver.isowner(f, destroot) or ver.isprotected(full_path)):
+ for ver in mypkglist:
+ if ver.isowner(f, destroot):
isowned = True
break
+ if not isowned and self.isprotected(full_path):
+ isowned = True
if not isowned:
stopmerge = True
if collision_ignore:
break
if stopmerge:
collisions.append(f)
- return collisions
+ return collisions, plib_collisions
+
+ def _lstat_inode_map(self, path_iter):
+ """
+ Use lstat to create a map of the form:
+ {(st_dev, st_ino) : set([path1, path2, ...])}
+ Multiple paths may reference the same inode due to hardlinks.
+ All lstat() calls are relative to self.myroot.
+ """
+ root = self.myroot
+ inode_map = {}
+ for f in path_iter:
+ path = os.path.join(root, f.lstrip(os.sep))
+ try:
+ st = os.lstat(path)
+ except OSError, e:
+ if e.errno not in (errno.ENOENT, errno.ENOTDIR):
+ raise
+ del e
+ continue
+ key = (st.st_dev, st.st_ino)
+ paths = inode_map.get(key)
+ if paths is None:
+ paths = set()
+ inode_map[key] = paths
+ paths.add(f)
+ return inode_map
def _security_check(self, installed_instances):
if not installed_instances:
blockers = self._blockers()
if blockers is None:
blockers = []
- collisions = self._collision_protect(srcroot, destroot,
+ collisions, plib_collisions = \
+ self._collision_protect(srcroot, destroot,
others_in_slot + blockers, myfilelist + mylinklist)
# Make sure the ebuild environment is initialized and that ${T}/elog
# just been merged.
others_in_slot.append(self) # self has just been merged
for dblnk in others_in_slot:
- dblnk.contentscache = None
- dblnk._contents_inodes = None
- dblnk._contents_basenames = None
+ dblnk._clear_contents_cache()
# If portage is reinstalling itself, remove the old
# version now since we want to use the temporary
# PORTAGE_BIN_PATH that will be removed when we return.
reinstall_self = False
if self.myroot == "/" and \
- "sys-apps" == self.cat and \
- "portage" == pkgsplit(self.pkg)[0]:
+ match_from_list(PORTAGE_PACKAGE_ATOM, [self.mycpv]):
reinstall_self = True
autoclean = self.settings.get("AUTOCLEAN", "yes") == "yes"
self.vartree.dbapi.removeFromContents(blocker, iter(contents),
relative_paths=False)
+ # Unregister any preserved libs that this package has overwritten
+ # and update the contents of the packages that owned them.
+ plib_registry = self.vartree.dbapi.plib_registry
+ plib_dict = plib_registry.getPreservedLibs()
+ for cpv, paths in plib_collisions.iteritems():
+ if cpv not in plib_dict:
+ continue
+ if cpv == self.mycpv:
+ continue
+ try:
+ slot, counter = self.vartree.dbapi.aux_get(
+ cpv, ["SLOT", "COUNTER"])
+ except KeyError:
+ continue
+ remaining = [f for f in plib_dict[cpv] if f not in paths]
+ plib_registry.register(cpv, slot, counter, remaining)
+ self.vartree.dbapi.removeFromContents(cpv, paths)
+
self.vartree.dbapi._add(self)
contents = self.getcontents()
if self.vartree.dbapi._categories is not None:
self.vartree.dbapi._categories = None
if self.myroot == "/" and \
- "sys-apps" == self.cat and \
- "portage" == pkgsplit(self.pkg)[0]:
+ match_from_list(PORTAGE_PACKAGE_ATOM, [self.mycpv]):
settings = self.settings
base_path_orig = os.path.dirname(settings["PORTAGE_BIN_PATH"])
from tempfile import mkdtemp
class _use_dep(object):
- __slots__ = ("__weakref__", "conditional", "conditional_disabled",
- "conditional_enabled", "disabled", "enabled", "tokens", "required")
+ __slots__ = ("__weakref__", "conditional",
+ "disabled", "enabled", "tokens", "required")
_conditionals_class = portage.cache.mappings.slot_dict_class(
("disabled", "enabled", "equal", "not_equal"), prefix="")
return _use_dep(tokens)
+ def _eval_qa_conditionals(self, use_mask, use_force):
+ """
+ For repoman, evaluate all possible combinations within the constraints
+ of the given use.force and use.mask settings. The result may seem
+ ambiguous in the sense that the same flag can be in both the enabled
+ and disabled sets, but this is useful within the context of how its
+ intended to be used by repoman. It is assumed that the caller has
+ already ensured that there is no intersection between the given
+ use_mask and use_force sets when necessary.
+ """
+ tokens = []
+
+ conditional = self.conditional
+ tokens.extend(self.enabled)
+ tokens.extend("-" + x for x in self.disabled)
+ tokens.extend(x for x in conditional.enabled if x not in use_mask)
+ tokens.extend("-" + x for x in conditional.disabled if x not in use_force)
+
+ tokens.extend(x for x in conditional.equal if x not in use_mask)
+ tokens.extend("-" + x for x in conditional.equal if x not in use_force)
+ tokens.extend("-" + x for x in conditional.not_equal if x not in use_mask)
+ tokens.extend(x for x in conditional.not_equal if x not in use_force)
+
+ return _use_dep(tokens)
+
class _AtomCache(type):
"""
Cache Atom instances from constructor calls and reuse