y=${x%.*}
y=${y##*.}
- myfail="${x} does not exist"
- if [ "${x:0:2}" = "./" ] ; then
+ if [[ ${x} == "./"* ]] ; then
srcdir=""
+ elif [[ ${x} == ${DISTDIR%/}/* ]] ; then
+ die "Arguments to unpack() cannot begin with \${DISTDIR}."
+ elif [[ ${x} == "/"* ]] ; then
+ die "Arguments to unpack() cannot be absolute"
else
srcdir="${DISTDIR}/"
fi
- [[ ${x} == ${DISTDIR}* ]] && \
- die "Arguments to unpack() should not begin with \${DISTDIR}."
- [ ! -s "${srcdir}${x}" ] && die "$myfail"
+ [[ ! -s ${srcdir}${x} ]] && die "${x} does not exist"
myfail="failure unpacking ${x}"
case "${x##*.}" in
[ ! -z "${OCXX}" ] && export CXX="${OCXX}"
}
+# Hardcoded bash lists are needed for backward compatibility with
+# <portage-2.1.4 since they assume that a newly installed version
+# of ebuild.sh will work for pkg_postinst, pkg_prerm, and pkg_postrm
+# when portage is upgrading itself.
+
READONLY_EBUILD_METADATA="DEPEND DESCRIPTION
EAPI HOMEPAGE INHERITED IUSE KEYWORDS LICENSE
PDEPEND PROVIDE RDEPEND RESTRICT SLOT SRC_URI"
READONLY_PORTAGE_VARS="D EBUILD EBUILD_PHASE \
- EBUILD_SH_ARGS EMERGE_FROM FILESDIR \
+ EBUILD_SH_ARGS EMERGE_FROM FILESDIR PORTAGE_BINPKG_FILE \
PORTAGE_BIN_PATH PORTAGE_PYM_PATH PORTAGE_MUTABLE_FILTERED_VARS \
PORTAGE_SAVED_READONLY_VARS PORTAGE_TMPDIR T WORKDIR ED"
# listed in READONLY_EBUILD_METADATA, since having any readonly attributes
# persisting in the saved environment can be inconvenient when it
# eventually needs to be reloaded.
- egrep -v -e "${var_grep}" | sed \
- -e 's:^declare[[:space:]]\+-r[[:space:]]\+::' \
- -e 's:^declare[[:space:]]\+-\([[:alnum:]]*\)r\([[:alnum:]]*\)[[:space:]]\+:declare -\1\2 :'
+ "${PORTAGE_BIN_PATH}"/filter-bash-environment.py "${var_grep}" | sed -r \
+ -e 's:^declare[[:space:]]+-r[[:space:]]+:declare :' \
+ -e 's:^declare[[:space:]]+-([[:alnum:]]*)r([[:alnum:]]*)[[:space:]]+:declare -\1\2 :'
}
# @FUNCTION: preprocess_ebuild_env
if __name__ == "__main__":
import sys
- from portage.exception import PermissionDenied
+ from portage.exception import ParseError, PermissionDenied
try:
retval = _emerge.emerge_main()
except PermissionDenied, e:
sys.stderr.write("Permission denied: '%s'\n" % str(e))
sys.exit(e.errno)
+ except ParseError, e:
+ sys.stderr.write("%s\n" % str(e))
+ sys.exit(1)
sys.exit(retval)
--- /dev/null
+#!/usr/bin/env python
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+import os, re, sys
+
+egrep_compat_map = {
+ "[:alnum:]" : r'\w',
+ "[:space:]" : r'\s',
+}
+
+here_doc_re = re.compile(r'.*\s<<[-]?(\w+)$')
+
+def compile_egrep_pattern(s):
+ for k, v in egrep_compat_map.iteritems():
+ s = s.replace(k, v)
+ return re.compile(s)
+
+def filter_bash_environment(pattern, file_in, file_out):
+ here_doc_delim = None
+ for line in file_in:
+ if here_doc_delim is not None:
+ if here_doc_delim.match(line):
+ here_doc_delim = None
+ file_out.write(line)
+ continue
+ here_doc = here_doc_re.match(line)
+ if here_doc is not None:
+ here_doc_delim = re.compile("^%s$" % here_doc.group(1))
+ file_out.write(line)
+ continue
+ if pattern.match(line) is None:
+ file_out.write(line)
+
+if __name__ == "__main__":
+ description = "Filter out any lines that match a given PATTERN " + \
+ "while leaving bash here-documents intact. The PATTERN should " + \
+ "use python regular expression syntax but [:space:] and " + \
+ "[:alnum:] character classes will be automatically translated " + \
+ "for compatibility with egrep syntax."
+ usage = "usage: %s PATTERN" % os.path.basename(sys.argv[0])
+ from optparse import OptionParser
+ parser = OptionParser(description=description, usage=usage)
+ options, args = parser.parse_args(sys.argv[1:])
+ if len(args) != 1:
+ parser.error("Missing required PATTERN argument.")
+ file_in = sys.stdin
+ file_out = sys.stdout
+ filter_bash_environment(
+ compile_egrep_pattern(args[0]), file_in, file_out)
+ file_out.flush()
sys.stderr.flush()
sys.exit(os.EX_USAGE)
os.environ["ROOT"] = sys.argv[2]
+
+ # First import the main portage module without legacy globals since it
+ # is almost certain to succeed in that case. This provides access to
+ # the portage.exception namespace which is needed for later exception
+ # handling, like if portage.exception.PermissionDenied is raised when
+ # constructing the legacy global config instance.
+ os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
+ import portage
+ del os.environ["PORTAGE_LEGACY_GLOBALS"]
try:
global portage
try:
- import portage
+ reload(portage)
except ImportError:
from os import path as osp
sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
except portage.exception.PermissionDenied, e:
sys.stderr.write("Permission denied: '%s'\n" % str(e))
sys.exit(e.errno)
+ except portage.exception.ParseError, e:
+ sys.stderr.write("%s\n" % str(e))
+ sys.exit(1)
except ValueError, e:
if not e.args or \
not hasattr(e.args[0], "__len__") or \
mynew = cvstree.findnew(mycvstree, recursive=1, basedir="./")
new_ebuilds.update(x for x in mynew if x.endswith(".ebuild"))
del mycvstree, mynew
+ if "commit" == options.mode and \
+ "RMD160" not in portage.checksum.hashorigin_map:
+ from portage.util import grablines
+ repo_lines = grablines("./CVS/Repository")
+ if repo_lines and \
+ "gentoo-x86" == repo_lines[0].strip().split(os.path.sep)[0]:
+ msg = "Please install " \
+ "pycrypto or enable python's ssl USE flag in order " \
+ "to enable RMD160 hash support. See bug #198398 for " \
+ "more information."
+ prefix = red(" * ")
+ from textwrap import wrap
+ for line in wrap(msg, 70):
+ print prefix + line
+ sys.exit(1)
dofail = 0
arch_caches={}
<part id='config'>
<title>Configuration</title>
+&config_bashrc;
&config_set;
</part>
--- /dev/null
+<chapter id='config-bashrc'>
+ <title>Bashrc Configuration</title>
+ <sect1 id='config-bashrc-locations'>
+ <title>bashrc locations</title>
+ <para>
+ If a bashrc file is located at <filename>/etc/portage/bashrc</filename>
+ then it will be sourced before an ebuild is executed.
+ </para>
+ </sect1>
+ <sect1 id='config-bashrc-ebuild-phase-hooks'>
+ <title>Ebuild Phase Hooks</title>
+ <para>
+ A phase hook function name begins with a pre_ or post_
+ prefix to indicate that it will be called before or after
+ one of the <link linkend='package-ebuild-phases'>ebuild phases</link>.
+ The prefix is followed by the name of the ebuild function that the hook
+ will be associated with. For example, a hook named pre_src_compile
+ will be called before src_compile, and a hook named post_src_compile
+ will be called after src_compile.
+ </para>
+ </sect1>
+</chapter>
--- /dev/null
+<part id='package'>
+<title>Package Formats</title>
+&package_ebuild;
+</part>
--- /dev/null
+<chapter id='package-ebuild'>
+<title>Ebuild</title>
+&package_ebuild_phases;
+</chapter>
--- /dev/null
+<sect1 id='package-ebuild-phases'>
+ <title>Ebuild Phases</title>
+ <para>
+ Ebuild execution is divided into a series of phases. In order
+ to implement a phase, an ebuild defines a function to serve as
+ an entry point for execution of that phase.
+ This design is similar to the template method pattern that
+ is commonly used in object oriented programming languages. An ebuild
+ can inherit or override a template method from an eclass.
+ </para>
+ <para>
+ The function names for the ebuild phases, listed in order of execution:
+ <itemizedlist>
+ <listitem>
+ pkg_setup
+ </listitem>
+ <listitem>
+ src_unpack
+ </listitem>
+ <listitem>
+ src_compile
+ </listitem>
+ <listitem>
+ src_test
+ </listitem>
+ <listitem>
+ src_install
+ </listitem>
+ <listitem>
+ pkg_preinst
+ </listitem>
+ <listitem>
+ pkg_postinst
+ </listitem>
+ <listitem>
+ pkg_prerm
+ </listitem>
+ <listitem>
+ pkg_postrm
+ </listitem>
+ </itemizedlist>
+ </para>
+</sect1>
<!ENTITY project "portage">
+ <!ENTITY package SYSTEM "package.docbook">
+ <!ENTITY package_ebuild SYSTEM "package/ebuild.docbook">
+ <!ENTITY package_ebuild_phases SYSTEM "package/ebuild/phases.docbook">
<!ENTITY qa SYSTEM "qa.docbook">
<!ENTITY config SYSTEM "config.docbook">
+ <!ENTITY config_bashrc SYSTEM "config/bashrc.docbook">
<!ENTITY config_set SYSTEM "config/sets.docbook">
]>
</bookinfo>
&config;
+&package;
&qa;
</book>
+<part id='qa'>
+<title>Quality Assurance</title>
<chapter id='qa-notices'>
<title>QA Notices</title>
<para>
</para>
</sect1>
</chapter>
+</part>
@rtype: Boolean
@returns: True if the package is visible, False otherwise.
"""
+ if not metadata["SLOT"]:
+ return False
if built and not installed and \
metadata["CHOST"] != pkgsettings["CHOST"]:
return False
mreasons.append("EPREFIX: '%s' too small" % metadata["EPREFIX"])
missing_licenses = []
if metadata:
+ if not metadata["SLOT"]:
+ mreasons.append("invalid: SLOT is undefined")
if not portage.eapi_is_supported(metadata["EAPI"]):
have_eapi_mask = True
try:
ldpath_mtimes = mtimedb["ldpath"]
xterm_titles = "notitles" not in self.settings.features
- #check for blocking dependencies
- if "--fetchonly" not in self.myopts and \
- "--fetch-all-uri" not in self.myopts and \
- "--buildpkgonly" not in self.myopts:
- for x in mylist:
- if x[0]=="blocks":
- print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
- print "!!! the two packages cannot be installed on the same system together."
- print "!!! Please use 'emerge --pretend' to determine blockers."
- if "--quiet" not in self.myopts:
- show_blocker_docs_link()
- return 1
-
if "--resume" in self.myopts:
# We're resuming.
print colorize("GOOD", "*** Resuming merge...")
("--pretend" in myopts),
mydbapi=trees[pkgline[1]]["porttree"].dbapi,
tree="porttree")
- if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
- pkglist = []
- for pkg in mydepgraph.altlist():
- if pkg[0] != "blocks":
- pkglist.append(pkg)
+
+ pkglist = mydepgraph.altlist()
+
+ if fetchonly or "--buildpkgonly" in myopts:
+ pkglist = [pkg for pkg in pkglist if pkg[0] != "blocks"]
else:
- pkglist = mydepgraph.altlist()
+ for x in pkglist:
+ if x[0] != "blocks":
+ continue
+ msg = "Error: the " + x[2] + " package conflicts " + \
+ "with another package; the two packages cannot " + \
+ "be installed on the same system together. " + \
+ "Please use 'emerge --pretend' to determine blockers."
+ prefix = red(" * ")
+ from textwrap import wrap
+ for line in wrap(msg, 70):
+ print prefix + line
+ if "--quiet" not in myopts:
+ show_blocker_docs_link()
+ return 1
+
mydepgraph.saveNomergeFavorites()
del mydepgraph
mergetask = MergeTask(settings, trees, myopts)
if "--pretend" in myopts:
display_news_notification(trees)
return retval
-
-if __name__ == "__main__":
- retval = emerge_main()
- sys.exit(retval)
"FEATURES", "FILESDIR", "HOME", "PATH",
"PKGUSE", "PKG_LOGDIR", "PKG_TMPDIR",
"PORTAGE_ACTUAL_DISTDIR", "PORTAGE_ARCHLIST",
- "PORTAGE_BASHRC", "PORTAGE_BINPKG_TMPFILE", "PORTAGE_BIN_PATH",
+ "PORTAGE_BASHRC",
+ "PORTAGE_BINPKG_FILE", "PORTAGE_BINPKG_TMPFILE",
+ "PORTAGE_BIN_PATH",
"PORTAGE_BUILDDIR", "PORTAGE_COLORMAP",
"PORTAGE_CONFIGROOT", "PORTAGE_DEBUG", "PORTAGE_DEPCACHEDIR",
"PORTAGE_GID", "PORTAGE_INST_GID", "PORTAGE_INST_UID",
# make.globals should not be relative to config_root
# because it only contains constants.
- try:
- self.mygcfg = getconfig(os.path.join(BPREFIX, "etc", "make.globals"))
+ self.mygcfg = getconfig(os.path.join(BPREFIX, "etc", "make.globals"))
+
+ if self.mygcfg is None:
+ self.mygcfg = {}
- if self.mygcfg is None:
- self.mygcfg = {}
- except SystemExit, e:
- raise
- except Exception, e:
- if debug:
- raise
- writemsg("!!! %s\n" % (e), noiselevel=-1)
- if not isinstance(e, EnvironmentError):
- writemsg("!!! Incorrect multiline literals can cause " + \
- "this. Do not use them.\n", noiselevel=-1)
- sys.exit(1)
self.configlist.append(self.mygcfg)
self.configdict["globals"]=self.configlist[-1]
self.make_defaults_use = []
self.mygcfg = {}
if self.profiles:
- try:
- mygcfg_dlists = [getconfig(os.path.join(x, "make.defaults")) for x in self.profiles]
- for cfg in mygcfg_dlists:
- if cfg:
- self.make_defaults_use.append(cfg.get("USE", ""))
- else:
- self.make_defaults_use.append("")
- self.mygcfg = stack_dicts(mygcfg_dlists, incrementals=portage.const.INCREMENTALS, ignore_none=1)
- #self.mygcfg = grab_stacked("make.defaults", self.profiles, getconfig)
- if self.mygcfg is None:
- self.mygcfg = {}
- except SystemExit, e:
- raise
- except Exception, e:
- if debug:
- raise
- writemsg("!!! %s\n" % (e), noiselevel=-1)
- if not isinstance(e, EnvironmentError):
- writemsg("!!! 'rm -Rf %s/usr/portage/profiles; " + \
- "emerge sync' may fix this. If it does\n" % EPREFIX,
- noiselevel=-1)
- writemsg("!!! not then please report this to " + \
- "bugs.gentoo.org and, if possible, a dev\n",
- noiselevel=-1)
- writemsg("!!! on #gentoo (irc.freenode.org)\n",
- noiselevel=-1)
- sys.exit(1)
- self.configlist.append(self.mygcfg)
- self.configdict["defaults"]=self.configlist[-1]
-
- try:
- self.mygcfg = getconfig(
- os.path.join(config_root, MAKE_CONF_FILE.lstrip(os.path.sep)),
- allow_sourcing=True)
+ mygcfg_dlists = [getconfig(os.path.join(x, "make.defaults")) \
+ for x in self.profiles]
+ for cfg in mygcfg_dlists:
+ if cfg:
+ self.make_defaults_use.append(cfg.get("USE", ""))
+ else:
+ self.make_defaults_use.append("")
+ self.mygcfg = stack_dicts(mygcfg_dlists,
+ incrementals=portage.const.INCREMENTALS, ignore_none=1)
if self.mygcfg is None:
self.mygcfg = {}
- except SystemExit, e:
- raise
- except Exception, e:
- if debug:
- raise
- writemsg("!!! %s\n" % (e), noiselevel=-1)
- if not isinstance(e, EnvironmentError):
- writemsg("!!! Incorrect multiline literals can cause " + \
- "this. Do not use them.\n", noiselevel=-1)
- sys.exit(1)
+ self.configlist.append(self.mygcfg)
+ self.configdict["defaults"]=self.configlist[-1]
+ self.mygcfg = getconfig(
+ os.path.join(config_root, MAKE_CONF_FILE.lstrip(os.path.sep)),
+ allow_sourcing=True)
+ if self.mygcfg is None:
+ self.mygcfg = {}
# Don't allow the user to override certain variables in make.conf
profile_only_variables = self.configdict["defaults"].get(
os.path.basename(MISC_SH_BINARY))
mycommand = " ".join([_shell_quote(misc_sh_binary),
"install_qa_check", "install_symlink_html_docs"])
+ _doebuild_exit_status_unlink(
+ mysettings.get("EBUILD_EXIT_STATUS_FILE"))
filter_calling_env_state = mysettings._filter_calling_env
if os.path.exists(os.path.join(mysettings["T"], "environment")):
mysettings._filter_calling_env = True
logfile=logfile, **kwargs)
finally:
mysettings._filter_calling_env = filter_calling_env_state
- if qa_retval:
+ msg = _doebuild_exit_status_check(mydo, mysettings)
+ if msg:
+ qa_retval = 1
+ from textwrap import wrap
+ from portage.elog.messages import eerror
+ for l in wrap(msg, 72):
+ eerror(l, phase=mydo, key=mysettings.mycpv)
+ if qa_retval != os.EX_OK:
writemsg("!!! install_qa_check failed; exiting.\n",
noiselevel=-1)
return qa_retval
mycpv = mysettings["CATEGORY"] + "/" + mysettings["PF"]
dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
misc_keys = ["LICENSE", "PROVIDE", "RESTRICT", "SRC_URI"]
- all_keys = dep_keys + misc_keys
+ other_keys = ["SLOT"]
+ all_keys = dep_keys + misc_keys + other_keys
metadata = dict(izip(all_keys, mydbapi.aux_get(mycpv, all_keys)))
class FakeTree(object):
def __init__(self, mydb):
if mydo not in invalid_dep_exempt_phases:
return 1
del k
+ if not metadata["SLOT"]:
+ writemsg("SLOT is undefined\n", noiselevel=-1)
+ if mydo not in invalid_dep_exempt_phases:
+ return 1
del mycpv, dep_keys, metadata, misc_keys, FakeTree, dep_check_trees
if "PORTAGE_TMPDIR" not in mysettings or \
fp.write(str(portage.checksum.perform_md5(mytbz2))+"\n")
fp.close()
+ # This gives bashrc users an opportunity to do various things
+ # such as remove binary packages after they're installed.
+ mysettings["PORTAGE_BINPKG_FILE"] = mytbz2
+ mysettings.backup_changes("PORTAGE_BINPKG_FILE")
debug = mysettings.get("PORTAGE_DEBUG", "") == "1"
# We want to install in "our" prefix, not the binary one
did_merge_phase = True
return retval
finally:
+ mysettings.pop("PORTAGE_BINPKG_FILE", None)
if tbz2_lock:
portage.locks.unlockfile(tbz2_lock)
if builddir_lock:
try:
f=open(mycfg,'r')
except IOError, e:
+ if e.errno == PermissionDenied.errno:
+ raise PermissionDenied(mycfg)
if e.errno != errno.ENOENT:
raise
return None
#invalid token
#lex.error_leader(self.filename,lex.lineno)
if not tolerant:
- writemsg("!!! Invalid token (not \"=\") "+str(equ)+"\n",
- noiselevel=-1)
- raise Exception("ParseError: Invalid token (not '='): "+str(mycfg)+": line "+str(lex.lineno))
+ raise Exception("ParseError: Invalid token " + \
+ "'%s' (not '='): %s: line %s" % \
+ (equ, mycfg, lex.lineno))
else:
return mykeys
val=lex.get_token()