# is only desired in certain cases, such as during preprocessing or when
# saving environment.bz2 for a binary or installed package.
#
+# --filter-features causes the special FEATURES variable to be filtered.
+# Generally, we want it to persist between phases since the user might
+# want to modify it via bashrc to enable things like splitdebug and
+# installsources for specific packages. They should be able to modify it
+# in pre_pkg_setup() and have it persist all the way through the install
+# phase. However, if FEATURES exist inside environment.bz2 then they
+# should be overridden by current settings.
+#
# ---allow-extra-vars causes some extra vars to be allowd through, such
# as ${PORTAGE_SAVED_READONLY_VARS} and ${PORTAGE_MUTABLE_FILTERED_VARS}.
#
PIPESTATUS PPID SHELLOPTS UID"
local filtered_sandbox_vars="SANDBOX_ACTIVE SANDBOX_BASHRC
SANDBOX_DEBUG_LOG SANDBOX_DISABLED SANDBOX_LIB
- SANDBOX_LOG"
+ SANDBOX_LOG SANDBOX_ON"
filtered_vars="${readonly_bash_vars} ${READONLY_PORTAGE_VARS}
BASH_[_[:alnum:]]*"
if hasq --filter-sandbox $* ; then
else
filtered_vars="${filtered_vars} ${filtered_sandbox_vars}"
fi
+ if hasq --filter-features $* ; then
+ filtered_vars="${filtered_vars} FEATURES"
+ fi
if ! hasq --allow-extra-vars $* ; then
filtered_vars="
${filtered_vars}
if [ -f "${T}/environment.raw" ] ; then
# This is a signal from the python side, indicating that the
# environment may contain stale SANDBOX_{DENY,PREDICT,READ,WRITE}
- # variables that should be filtered out. Between phases, these
- # variables are normally preserved.
- filter_opts="--filter-sandbox ${filter_opts}"
+ # and FEATURES variables that should be filtered out. Between
+ # phases, these variables are normally preserved.
+ filter_opts="--filter-sandbox --filter-features ${filter_opts}"
fi
filter_readonly_variables ${filter_opts} < "${T}"/environment \
> "${T}"/environment.filtered || return $?
# called. Any variables that need to be relied upon should already be
# filtered out above.
(
+ export SANDBOX_ON=1
source "${T}/environment" || exit $?
+ # We have to temporarily disable sandbox since the
+ # SANDBOX_{DENY,READ,PREDICT,WRITE} values we've just loaded
+ # may be unusable (triggering in spurious sandbox violations)
+ # until we've merged them with our current values.
+ export SANDBOX_ON=0
# It's remotely possible that save_ebuild_env() has been overridden
# by the above source command. To protect ourselves, we override it
for x in SANDBOX_DENY SANDBOX_READ SANDBOX_PREDICT SANDBOX_WRITE ; do
eval PORTAGE_${x}=\${!x}
done
+ PORTAGE_SANDBOX_ON=${SANDBOX_ON}
+ export SANDBOX_ON=1
source "${T}"/environment || \
die "error sourcing environment"
+ # We have to temporarily disable sandbox since the
+ # SANDBOX_{DENY,READ,PREDICT,WRITE} values we've just loaded
+ # may be unusable (triggering in spurious sandbox violations)
+ # until we've merged them with our current values.
+ export SANDBOX_ON=0
for x in SANDBOX_DENY SANDBOX_PREDICT SANDBOX_READ SANDBOX_WRITE ; do
eval y=\${PORTAGE_${x}}
if [ "${y}" != "${!x}" ] ; then
unset PORTAGE_${x}
done
unset x y
+ export SANDBOX_ON=${PORTAGE_SANDBOX_ON}
+ unset PORTAGE_SANDBOX_ON
source_all_bashrcs
else
from portage.sets import load_default_config
setconfig = load_default_config(portage.settings,
portage.db[portage.settings["ROOT"]])
- self._sets = setconfig.getSetsWithAliases()
+ self._sets = setconfig.getSets()
def _check_world(self, onProgress):
categories = set(portage.settings.categories)
unset BAD BRACKET BUILD_PREFIX COLS \
DISTCC_DIR DISTDIR DOC_SYMLINKS_DIR \
EBUILD_EXIT_STATUS_FILE EBUILD_MASTER_PID \
- ECLASSDIR ECLASS_DEPTH ENDCOL FAKEROOTKEY FEATURES \
+ ECLASSDIR ECLASS_DEPTH ENDCOL FAKEROOTKEY \
GOOD HILITE HOME IMAGE \
LAST_E_CMD LAST_E_LEN LD_PRELOAD MISC_FUNCTIONS_ARGS MOPREFIX \
NORMAL PATH PKGDIR PKGUSE PKG_LOGDIR PKG_TMPDIR \
PORTAGE_DEPCACHEDIR PORTAGE_GID PORTAGE_INST_GID \
PORTAGE_INST_UID PORTAGE_LOG_FILE PORTAGE_MASTER_PID \
PORTAGE_REPO_NAME PORTAGE_RESTRICT PORTAGE_WORKDIR_MODE PORTDIR \
- PORTDIR_OVERLAY PREROOTPATH \
+ PORTDIR_OVERLAY ${!PORTAGE_SANDBOX_*} PREROOTPATH \
PROFILE_PATHS PWORKDIR QA_INTERCEPTORS \
RC_DEFAULT_INDENT RC_DOT_PATTERN RC_ENDCOL \
RC_INDENTATION READONLY_EBUILD_METADATA READONLY_PORTAGE_VARS \
# Compiled python objects do not belong in /usr/share (FHS violation)
# and can be a pain when upgrading python
- f=$([ -d "${ED}"/usr/share ] && find "${ED}"/usr/share -name '*.py[co]')
+ f=$([ -d "${ED}"/usr/share ] && \
+ find "${ED}"usr/share -name '*.py[co]' | sed "s:${D}:/:")
if [[ -n ${f} ]] ; then
vecho -ne '\a\n'
eqawarn "QA Notice: Precompiled python object files do not belong in /usr/share"
#!@BASH@
# Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
-# $Id:$
+# $Id$
source "${PORTAGE_BIN_PATH:-${EPREFIX}/usr/lib/portage/bin}"/isolated-functions.sh
# The existance of the section .symtab tells us that a binary is stripped.
# We want to log already stripped binaries, as this may be a QA violation.
# They prevent us from getting the splitdebug data.
-f=$(scanelf -yqRBF '#k%F' -k '!.symtab' "$@")
-if [[ -n ${f} ]] ; then
- vecho -e "\a\n"
- eqawarn "QA Notice: Pre-stripped files found:"
- eqawarn "${f}"
- echo "${f}" > "${T}"/scanelf-already-stripped.log
+if ! hasq binchecks ${RESTRICT} && \
+ ! hasq strip ${RESTRICT} ; then
+ f=$(scanelf -yqRBF '#k%F' -k '!.symtab' "$@")
+ if [[ -n ${f} ]] ; then
+ vecho -e "\a\n"
+ eqawarn "QA Notice: Pre-stripped files found:"
+ eqawarn "${f}"
+ echo "${f}" > "${T}"/scanelf-already-stripped.log
+ fi
fi
# Now we look for unstripped binaries.
import codecs
import errno
+import formatter
import logging
import optparse
import os
except ImportError:
import pickle
+try:
+ import cStringIO as StringIO
+except ImportError:
+ import StringIO
+
if not hasattr(__builtins__, "set"):
from sets import Set as set
from portage.util import initialize_logger
from portage.output import bold, create_color_func, darkgreen, \
green, nocolor, red, turquoise, yellow
+from portage.output import ConsoleStyleFile, StyleWriter
initialize_logger()
# file.executable
no_exec = frozenset(["Manifest","ChangeLog","metadata.xml"])
+def editor_is_executable(editor):
+ """
+ Given an EDITOR string, validate that it refers to
+ an executable. This uses shlex.split() to split the
+ first component and do a PATH lookup if necessary.
+
+ @param editor: An EDITOR value from the environment.
+ @type: string
+ @rtype: bool
+ @returns: True if an executable is found, False otherwise.
+ """
+ import shlex
+ editor_split = shlex.split(editor)
+ if not editor_split:
+ return False
+ filename = editor_split[0]
+ if not os.path.isabs(filename):
+ from portage.process import find_binary
+ return find_binary(filename) is not None
+ return os.access(filename, os.X_OK) and os.path.isfile(filename)
+
+def get_commit_message_with_editor(editor, message=None):
+ """
+ Execute editor with a temporary file as it's argument
+ and return the file content afterwards.
+
+ @param editor: An EDITOR value from the environment
+ @type: string
+ @param message: An iterable of lines to show in the editor.
+ @type: iterable
+ @rtype: string or None
+ @returns: A string on success or None if an error occurs.
+ """
+ from tempfile import mkstemp
+ fd, filename = mkstemp()
+ try:
+ os.write(fd, "\n# Please enter the commit message " + \
+ "for your changes.\n# (Comment lines starting " + \
+ "with '#' will not be included)\n")
+ if message:
+ os.write(fd, "#\n")
+ for line in message:
+ os.write(fd, "#" + line)
+ os.close(fd)
+ retval = os.system(editor + " '%s'" % filename)
+ if not (os.WIFEXITED(retval) and os.WEXITSTATUS(retval) == os.EX_OK):
+ return None
+ try:
+ mylines = open(filename).readlines()
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ raise
+ del e
+ return None
+ return "".join(line for line in mylines if not line.startswith("#"))
+ finally:
+ try:
+ os.unlink(filename)
+ except OSError:
+ pass
+
+def get_commit_message_with_stdin():
+ """
+ Read a commit message from the user and return it.
+
+ @rtype: string or None
+ @returns: A string on success or None if an error occurs.
+ """
+ print "Please enter a commit message. Use Ctrl-d to finish or Ctrl-c to abort."
+ commitmessage = []
+ while True:
+ commitmessage.append(sys.stdin.readline())
+ if not commitmessage[-1]:
+ break
+ commitmessage = "".join(commitmessage)
+ return commitmessage
+
+def format_qa_output(f, stats, fails, dofull, dofail):
+ full = options.mode in ("full", "lfull")
+ for x in qacats:
+ if not stats[x]:
+ continue
+ f.add_literal_data(" " + x.ljust(30))
+ if x in qawarnings:
+ f.push_style("WARN")
+ else:
+ f.push_style("BAD")
+ f.add_literal_data(str(stats[x]))
+ f.pop_style()
+ f.add_line_break()
+ if not dofull:
+ if not full and dofail and x in qawarnings:
+ # warnings are considered noise when there are failures
+ continue
+ fails_list = fails[x]
+ if not full and len(fails_list) > 12:
+ fails_list = fails_list[:12]
+ for y in fails_list:
+ f.add_literal_data(" "+y)
+ f.add_line_break()
+
def last(full=False):
"""Print the results of the last repoman run
Args:
#dofull will be set if we should print a "repoman full" informational message
dofull=0
- print
- print green("RepoMan remembers...")
- print
+ dofull = options.mode not in ("full", "lfull")
+
for x in qacats:
- if stats[x]:
- dowarn=1
- if x not in qawarnings:
- dofail=1
- else:
+ if not stats[x]:
continue
- print " "+ x.ljust(20),
- if stats[x]==0:
- print green(`stats[x]`)
+ if "notadded" in x and not isCvs:
+ stats[x] = 0
continue
- elif x in qawarnings:
- print yellow(`stats[x]`)
- else:
- print red(`stats[x]`)
- if not full:
- if stats[x]<12:
- for y in fails[x]:
- print " "+y
- else:
- dofull=1
- else:
- for y in fails[x]:
- print " "+y
+ dowarn = 1
+ if x not in qawarnings:
+ dofail = 1
+
+ print
+ print green("RepoMan remembers...")
+ print
+ style_file = ConsoleStyleFile(sys.stdout)
+ console_writer = StyleWriter(file=style_file, maxcol=9999)
+ console_writer.style_listener = style_file.new_styles
+ f = formatter.AbstractFormatter(console_writer)
+ format_qa_output(f, stats, fails, dofull, dofail)
print
if dofull:
print bold("Note: type \"repoman lfull\" for a complete listing of repomans last run.")
"pycrypto or enable python's ssl USE flag in order " \
"to enable RMD160 hash support. See bug #198398 for " \
"more information."
- prefix = red(" * ")
+ prefix = bad(" * ")
from textwrap import wrap
for line in wrap(msg, 70):
print prefix + line
#dowarn will be set to 1 if we tripped any warnings
dowarn=0
#dofull will be set if we should print a "repoman full" informational message
-dofull=0
+dofull = options.mode not in ("full", "lfull")
+
for x in qacats:
- if not isCvs and not isSvn and (x.find("notadded") != -1):
- stats[x] = 0
- if stats[x]:
- dowarn=1
- if x not in qawarnings:
- dofail=1
- else:
+ if not stats[x]:
continue
- print " "+x.ljust(30),
- if stats[x]==0:
- print green(`stats[x]`)
+ if "notadded" in x and not isCvs and not isSvn:
+ stats[x] = 0
continue
- elif x in qawarnings:
- print yellow(`stats[x]`)
- else:
- print red(`stats[x]`)
- if options.mode !="full":
- if stats[x]<12:
- for y in fails[x]:
- print " "+y
- else:
- dofull=1
- else:
- for y in fails[x]:
- print " "+y
+ dowarn = 1
+ if x not in qawarnings:
+ dofail = 1
+
+if dofail or \
+ (dowarn and not (options.quiet or options.mode == "scan")):
+ dofull = 0
+
+# Save QA output so that it can be conveniently displayed
+# in $EDITOR while the user creates a commit message.
+# Otherwise, the user would not be able to see this output
+# once the editor has taken over the screen.
+qa_output = StringIO.StringIO()
+style_file = ConsoleStyleFile(sys.stdout)
+if options.mode == 'commit' and \
+ (not commitmessage or not commitmessage.strip()):
+ style_file.write_listener = qa_output
+console_writer = StyleWriter(file=style_file, maxcol=9999)
+console_writer.style_listener = style_file.new_styles
+
+f = formatter.AbstractFormatter(console_writer)
+
+format_qa_output(f, stats, fails, dofull, dofail)
+
+style_file.flush()
+del console_writer, f, style_file
+qa_output = qa_output.getvalue()
+qa_output = qa_output.splitlines(True)
def grouplist(mylist,seperator="/"):
"""(list,seperator="/") -- Takes a list of elements; groups them into
raise
# We've read the content so the file is no longer needed.
commitmessagefile = None
- if not commitmessage:
- print "Please enter a CVS commit message at the prompt:"
- while not commitmessage:
- try:
- commitmessage=raw_input(green("> "))
- except KeyboardInterrupt:
- exithandler()
+ if not commitmessage or not commitmessage.strip():
+ try:
+ editor = os.environ.get("EDITOR")
+ if editor and editor_is_executable(editor):
+ commitmessage = get_commit_message_with_editor(
+ editor, message=qa_output)
+ else:
+ commitmessage = get_commit_message_with_stdin()
+ except KeyboardInterrupt:
+ exithandler()
+ if not commitmessage or not commitmessage.strip():
+ print "* no commit message? aborting commit."
+ sys.exit(1)
+ commitmessage = commitmessage.rstrip()
portage_version = getattr(portage, "VERSION", None)
if portage_version is None:
sys.stderr.write("Failed to insert portage version in message!\n")
<!-- TODO: Add reference to currently non-existing documentation about
set usage and default sets -->
After that it will read repository specific configurations from
- <envar>PORTDIR</envar> and <envar>PORTDIR_OVERLAY</envar>that might
+ <envar>PORTDIR</envar> and <envar>PORTDIR_OVERLAY</envar> that might
include definitions of sets included in the repository.
Finally a system-specific set configuration may reside in
<filename>/etc/portage</filename> to either define additional sets or
<para>
Unlike other Portage configuration files <filename>sets.conf</filename>
uses Pythons <classname>ConfigParser</classname> module, which implements
- the syntax usually found in .ini files. At it's core it allows various
+ the syntax usually found in .ini files. At its core it allows various
named sections that each can contain any number of key-value pairs, see
the <ulink url="http://doc.python.org/lib/module-ConfigParser.html" type="text/html">Python documentation</ulink>
for the full details.
it only requires a single option <varname>class</varname> to be
complete <footnote><para>Technically the <varname>class</varname> option
isn't stricly required, but it should always be used as the default
- handler might be changed in future versions</para></footnote>.
+ handler might be changed in future versions.</para></footnote>.
That option defines which handler class should be used to
create the set. Another universal option available for single sets is
<varname>name</varname>, however it's usually not needed as the name
<title>portage.sets.security.NewAffectedSet</title>
<para>
Like <xref linkend='config-set-classes-SecuritySet'>SecuritySet</xref>,
- but ignores all GLSAs that were already applied or inejcted previously,
+ but ignores all GLSAs that were already applied or injected previously,
and all GLSAs that don't affect the current system. Practically there
should be no difference to <classname>NewGlsaSet</classname> though.
</para>
<listitem><varname>only_visible</varname>: Optional, defaults to <parameter>true</parameter>.
When set to <parameter>true</parameter> the set will only include visible packages,
when set to <parameter>false</parameter> it will also include masked packages.
- It's currently only effective in in combination with the <parameter>porttree</parameter>
+ It's currently only effective in combination with the <parameter>porttree</parameter>
repository.
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Perl - some versions of perl would use incorrect -rpath flags</para>
- <para>Solution: upgrade system perl build modules</para>
+ <para>Solution: Upgrade system perl build modules</para>
</listitem>
<listitem>
<para>Crappy build system - the custom build system uses -rpath incorrectly</para>
- <para>Solution: review the LDFLAGS in the build system and make them not suck</para>
+ <para>Solution: Review the LDFLAGS in the build system and make them not suck</para>
</listitem>
<listitem>
<para>Crappy ebuild - the ebuild installs ELFs instead of using the package's build system</para>
- <para>Solution: fix the crappy ebuild to use the package's build system</para>
+ <para>Solution: Fix the crappy ebuild to use the package's build system</para>
</listitem>
</itemizedlist>
</para>
.TP
\fBCONFIG_PROTECT\fR = \fI[space delimited list of files and/or directories]\fR
All files and/or directories that are defined here will have "config file protection"
-enabled for them. For more information, please see `emerge \-\-help config`.
+enabled for them. See the \fBCONFIGURATION FILES\fR section
+of \fBemerge\fR(1) for more information.
.TP
\fBCONFIG_PROTECT_MASK\fR = \fI[space delimited list of files and/or directories]\fR
All files and/or directories that are defined here will have "config file protection"
-disabled for them. For more information, please see `emerge \-\-help config`.
+disabled for them. See the \fBCONFIGURATION FILES\fR section
+of \fBemerge\fR(1) for more information.
.TP
.B CTARGET
This variable is passed by the \fIebuild scripts\fR to the \fIconfigure\fR
def _accept_collisions(self):
acceptable = False
- for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
+ for x in ("--buildpkgonly", "--fetchonly",
+ "--fetch-all-uri", "--nodeps", "--pretend"):
if x in self.myopts:
acceptable = True
break
def saveNomergeFavorites(self):
"""Find atoms in favorites that are not in the mergelist and add them
to the world file if necessary."""
- for x in ("--fetchonly", "--fetch-all-uri",
+ for x in ("--buildpkgonly", "--fetchonly", "--fetch-all-uri",
"--oneshot", "--onlydeps", "--pretend"):
if x in self.myopts:
return
"with another package; the two packages cannot " + \
"be installed on the same system together. " + \
"Please use 'emerge --pretend' to determine blockers."
- prefix = red(" * ")
+ prefix = bad(" * ")
from textwrap import wrap
for line in wrap(msg, 70):
print prefix + line
except KeyError:
# masked by corruption
continue
+ if not metadata["SLOT"]:
+ continue
if getMaskAtom(cpv, metadata):
continue
if getProfileMaskAtom(cpv, metadata):
import commands
import errno
+import formatter
import os
import re
import shlex
for c in compat_functions_colors:
globals()[c] = create_color_func(c)
+class ConsoleStyleFile(object):
+ """
+ A file-like object that behaves something like
+ the colorize() function. Style identifiers
+ passed in via the new_styles() method will be used to
+ apply console codes to output.
+ """
+ def __init__(self, f):
+ self._file = f
+ self._styles = None
+ self.write_listener = None
+
+ def new_styles(self, styles):
+ self._styles = styles
+
+ def write(self, s):
+ if self._styles:
+ for style in self._styles:
+ self._file.write(codes[style])
+ self._file.write(s)
+ self._file.write(codes["reset"])
+ else:
+ self._file.write(s)
+ if self.write_listener:
+ self.write_listener.write(s)
+
+ def writelines(self, lines):
+ for s in lines:
+ self.write(s)
+
+ def flush(self):
+ self._file.flush()
+
+ def close(self):
+ self._file.close()
+
+class StyleWriter(formatter.DumbWriter):
+ """
+ This is just a DumbWriter with a hook in the new_styles() method
+ that passes a styles tuple as a single argument to a callable
+ style_listener attribute.
+ """
+ def __init__(self, **kwargs):
+ formatter.DumbWriter.__init__(self, **kwargs)
+ self.style_listener = None
+
+ def new_styles(self, styles):
+ formatter.DumbWriter.new_styles(self, styles)
+ if self.style_listener:
+ self.style_listener(styles)
+
def get_term_size():
"""
Get the number of lines and columns of the tty that is connected to