fi
if [ "${newstuff}" == "yes" ]; then
# We don't necessarily have privileges to do a full dyn_clean here.
+ rm -rf "${PORTAGE_BUILDDIR}"/{.unpacked,.compiled,.tested,.packaged,build-info}
rm -rf "${WORKDIR}"
if [ -d "${T}" ] && \
! hasq keeptemp $FEATURES && ! hasq keepwork $FEATURES ; then
set +o noglob
quiet_mode || einfo "Removing ${no_inst}"
# normal stuff
- rm -Rf ${root}/${no_inst} >&/dev/null
+ rm -Rf "${root}"/${no_inst} >&/dev/null
# we also need to handle globs (*.a, *.h, etc)
find "${root}" -path "${no_inst}" -exec rm -fR {} \; >/dev/null
eerror "${FUNCNAME}: D is unset"
return 1
fi
+
+ # Make sure $PWD is not ${D} so that we don't leave gmon.out files
+ # in there in case any tools were built with -pg in CFLAGS.
+ cd "${T}"
+
# remove man pages, info pages, docs if requested
for f in man info doc; do
if hasq no${f} $FEATURES; then
}
dyn_package() {
- cd "${PORTAGE_BUILDDIR}/image"
+ # Make sure $PWD is not ${D} so that we don't leave gmon.out files
+ # in there in case any tools were built with -pg in CFLAGS.
+ cd "${T}"
install_mask "${PORTAGE_BUILDDIR}/image" "${PKG_INSTALL_MASK}"
local tar_options=""
[ "${PORTAGE_QUIET}" == "1" ] || tar_options="${tar_options} -v"
[ -z "${PORTAGE_BINPKG_TMPFILE}" ] && \
PORTAGE_BINPKG_TMPFILE="${PKGDIR}/${CATEGORY}/${PF}.tbz2"
mkdir -p "${PORTAGE_BINPKG_TMPFILE%/*}" || die "mkdir failed"
- tar $tar_options -cf - $PORTAGE_BINPKG_TAR_OPTS . | \
+ tar $tar_options -cf - $PORTAGE_BINPKG_TAR_OPTS -C "${D}" . | \
bzip2 -f > "$PORTAGE_BINPKG_TMPFILE" || \
die "Failed to create tarball"
- cd ..
export PYTHONPATH=${PORTAGE_PYM_PATH:-${EPREFIX}/usr/lib/portage/pym}
python -c "from portage import xpak; t=xpak.tbz2('${PORTAGE_BINPKG_TMPFILE}'); t.recompose('${PORTAGE_BUILDDIR}/build-info')"
if [ $? -ne 0 ]; then
default=False, help='ignore masked packages (not allowed with commit mode)')
parser.add_option('--without-mask', dest='without_mask', action='store_true',
- default=False, help='behave as if no package.mask entries exist')
+ default=False, help='behave as if no package.mask entries exist (not allowed with commit mode)')
parser.add_option('--mode', type='choice', dest='mode', choices=modes.keys(),
help='specify which mode repoman will run in (default=full)')
if not opts.mode:
opts.mode = 'full' #default to full
- if opts.mode == 'commit' and opts.ignore_masked:
- parser.error('Commit mode and --ignore_masked are not compatable')
+ if opts.mode == 'commit' and not (opts.force or opts.pretend):
+ if opts.ignore_masked:
+ parser.error('Commit mode and --ignore-masked are not compatable')
+ if opts.without_mask:
+ parser.error('Commit mode and --without-mask are not compatable')
# Use the verbosity and quiet options to fiddle with the loglevel appropriately
for val in range(opts.verbosity):
"changelog.missing":"Missing ChangeLog files",
"ebuild.disjointed":"Ebuilds not added to cvs when the matching digest has been added",
"ebuild.notadded":"Ebuilds that exist but have not been added to cvs",
+ "ebuild.patches":"PATCHES variable should be a bash array to ensure white space safety",
"changelog.notadded":"ChangeLogs that exist but have not been added to cvs",
"filedir.missing":"Package lacks a files directory",
"file.executable":"Ebuilds, digests, metadata.xml, Manifest, and ChangeLog do note need the executable bit",
"file.size":"Files in the files directory must be under 20k",
"file.name":"File/dir name must be composed of only the following chars: %s " % allowed_filename_chars,
"file.UTF8":"File is not UTF8 compliant",
+ "java.eclassesnotused":"With virtual/jdk in DEPEND you must inherit a java eclass",
"KEYWORDS.dropped":"Ebuilds that appear to have dropped KEYWORDS for some arch",
"KEYWORDS.missing":"Ebuilds that have a missing or empty KEYWORDS variable",
"KEYWORDS.stable":"Ebuilds that have been added directly with stable KEYWORDS",
"RESTRICT.invalid",
"ebuild.minorsyn",
"ebuild.badheader",
+"ebuild.patches",
"file.size",
+"java.eclassesnotused",
"metadata.missing",
"metadata.bad",
"virtual.versioned",
myaux = ebuild_metadata[y]
eapi = myaux["EAPI"]
+ inherited = myaux["INHERITED"].split()
# Test for negative logic and bad words in the RESTRICT var.
#for x in myaux[allvars.index("RESTRICT")].split():
myflag = myflag[1:]
myiuse.add(myflag)
+ inherited_java_eclass = "java-pkg" in inherited
operator_tokens = set(["||", "(", ")"])
type_list, badsyntax = [], []
for mytype in ("DEPEND", "RDEPEND", "PDEPEND", "LICENSE", "PROVIDE"):
if not portage.isvalidatom(token, allow_blockers=True):
badsyntax.append("'%s' not a valid atom" % token)
else:
- atom = token.lstrip("!")
+ atom = token
+ is_blocker = atom.startswith("!")
+ if is_blocker:
+ atom = token.lstrip("!")
+ if mytype == "DEPEND" and \
+ not is_blocker and \
+ not inherited_java_eclass and \
+ portage.dep_getkey(atom) == "virtual/jdk":
+ stats['java.eclassesnotused'] += 1
+ fails['java.eclassesnotused'].append(relative_path)
if eapi == "0":
if portage.dep.dep_getslot(atom):
stats['EAPI.incompatible'] += 1
Use this variable if you want to selectively prevent certain files from being
copied into your file system tree. This does not work on symlinks, but only on
actual files. Useful if you wish to filter out files like HACKING.gz and
-TODO.gz.
+TODO.gz. The \fBINSTALL_MASK\fR is processed just before a package is merged.
+Also supported is a \fBPKG_INSTALL_MASK\fR variable that behaves exactly like
+\fBINSTALL_MASK\fR except that it is processed just before creation of a binary
+package.
.TP
.B MAKEOPTS
Use this variable if you want to use parallel make. For example, if you
Ignore masked packages (not allowed with commit mode)
.TP
\fB\-\-without\-mask\fR
-Behave as if no package.mask entries exist
+Behave as if no package.mask entries exist (not allowed with commit mode)
.TP
\fB-m\fR, \fB--commitmsg\fR
Adds a commit message via the command line
.B ebuild.output
A simple sourcing of the ebuild produces output; this breaks ebuild policy.
.TP
+.B ebuild.patches
+PATCHES variable should be a bash array to ensure white space safety
+.TP
.B ebuild.syntax
Error generating cache entry for ebuild; typically caused by ebuild syntax error
or digest verification failure.
.B filedir.missing
Package lacks a files directory
.TP
+.B java.eclassesnotused
+With virtual/jdk in DEPEND you must inherit a java eclass. Refer to
+\fIhttp://www.gentoo.org/proj/en/java/java\-devel.xml\fR for more information.
+.TP
.B metadata.bad
Bad metadata.xml files
.TP
self._pprovided_args = []
self._missing_args = []
self._masked_installed = []
+ self._unsatisfied_deps_for_display = []
self._dep_stack = []
self._unsatisfied_deps = []
self._ignored_deps = []
already been selected) will be required in order to handle all possible
cases."""
+ if not self._slot_collision_info:
+ return
+
msg = []
msg.append("\n!!! Multiple versions within a single " + \
"package slot have been \n")
if allow_unsatisfied:
self._unsatisfied_deps.append(dep)
continue
- self._show_unsatisfied_dep(dep.root, dep.atom,
- myparent=dep.parent)
+ self._unsatisfied_deps_for_display.append(
+ ((dep.root, dep.atom), {"myparent":dep.parent}))
return 0
# In some cases, dep_check will return deps that shouldn't
# be proccessed any further, so they are identified and
myslots = set()
for cpv in vardb.match(mykey):
myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
- if myslots:
- self._populate_filtered_repo(root, atom,
- exclude_installed=True)
- mymatches = filtered_db.match(atom)
- best_pkg = portage.best(mymatches)
- if best_pkg:
- best_slot = filtered_db.aux_get(best_pkg, ["SLOT"])[0]
- myslots.add(best_slot)
- if len(myslots) > 1:
- for myslot in myslots:
- myslot_atom = "%s:%s" % (mykey, myslot)
- self._populate_filtered_repo(
- root, myslot_atom,
- exclude_installed=True)
- if filtered_db.match(myslot_atom):
- yield myslot_atom
-
- # Since populate_filtered_repo() was called with the
- # exclude_installed flag, these atoms will need to be processed
- # again in case installed packages are required to satisfy
- # dependencies.
- self._filtered_trees[root]["atoms"].clear()
+ for myslot in myslots:
+ yield "%s:%s" % (mykey, myslot)
+ # In addition to any installed slots, also try to pull
+ # in the latest new slot that may be available.
+ yield atom
def _iter_args_for_pkg(self, pkg):
# TODO: add multiple $ROOT support
if not pkg:
if not (isinstance(arg, SetArg) and \
arg.name in ("system", "world")):
- self._show_unsatisfied_dep(myroot, atom)
+ self._unsatisfied_deps_for_display.append(
+ ((myroot, atom), {}))
return 0, myfavorites
self._missing_args.append((arg, atom))
continue
if pkg.installed and "selective" not in self.myparams:
- self._show_unsatisfied_dep(myroot, atom)
+ self._unsatisfied_deps_for_display.append(
+ ((myroot, atom), {}))
return 0, myfavorites
self._dep_stack.append(
myuse=myuse, strict=strict)
if True:
try:
+ self.trees[root]["selective"] = "selective" in self.myparams
if not strict:
portage.dep._dep_check_strict = False
mycheck = portage.dep_check(depstring, None,
pkgsettings, myuse=myuse,
myroot=root, trees=trees)
finally:
+ self.trees[root]["selective"] = False
portage.dep._dep_check_strict = True
if not mycheck[0]:
raise portage.exception.InvalidDependString(mycheck[1])
# unresolvable blocks.
for x in self.altlist():
if x[0] == "blocks":
+ self._slot_collision_info.clear()
return True
- self._show_slot_collision_notice()
if not self._accept_collisions():
return False
return True
#we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
#param is used for -u, where you still *do* want to see when something is being upgraded.
- myoldbest = ""
+ myoldbest = []
myinslotlist = None
installed_versions = vardb.match(portage.cpv_getkey(pkg_key))
if vardb.cpv_exists(pkg_key):
portage.cpv_getkey(pkg_key):
myinslotlist = None
if myinslotlist:
- myoldbest = portage.best(myinslotlist)
+ myoldbest = myinslotlist[:]
addl = " " + fetch
- if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
+ if not portage.dep.cpvequal(pkg_key,
+ portage.best([pkg_key] + myoldbest)):
# Downgrade in slot
addl += turquoise("U")+blue("D")
if ordered:
cur_use = [flag for flag in cur_use if flag in cur_iuse]
if myoldbest and myinslotlist:
- pkg = myoldbest
+ pkg = myoldbest[0]
else:
pkg = x[2]
if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
indent = " " * depth
- if myoldbest:
- if myinslotlist:
- myoldbest = [myoldbest]
- for key in myoldbest:
- pos = myoldbest.index(key)
- key = portage.pkgsplit(key)[1] + "-" + portage.pkgsplit(key)[2]
+ # Convert myoldbest from a list to a string.
+ if not myoldbest:
+ myoldbest = ""
+ else:
+ for pos, key in enumerate(myoldbest):
+ key = portage.catpkgsplit(key)[2] + \
+ "-" + portage.catpkgsplit(key)[3]
if key[-3:] == "-r0":
key = key[:-3]
myoldbest[pos] = key
myoldbest = blue("["+", ".join(myoldbest)+"]")
-
pkg_cp = xs[0]
root_config = self.roots[myroot]
print bold('*'+revision)
sys.stdout.write(text)
+ self.display_problems()
+ return os.EX_OK
+
+ def display_problems(self):
+ """
+ Display problems with the dependency graph such as slot collisions.
+ This is called internally by display() to show the problems _after_
+ the merge list where it is most likely to be seen, but if display()
+ is not going to be called then this method should be called explicitly
+ to ensure that the user is notified of problems with the graph.
+ """
+
+ self._show_slot_collision_notice()
+
# TODO: Add generic support for "set problem" handlers so that
# the below warnings aren't special cases for world only.
msg.append("The best course of action depends on the reason that an offending\n")
msg.append("package.provided entry exists.\n\n")
sys.stderr.write("".join(msg))
- return os.EX_OK
+
+ for pargs, kwargs in self._unsatisfied_deps_for_display:
+ self._show_unsatisfied_dep(*pargs, **kwargs)
def calc_changelog(self,ebuildpath,current,next):
if ebuildpath == None or not os.path.exists(ebuildpath):
merge_count = 0
pretend = "--pretend" in myopts
fetchonly = "--fetchonly" in myopts or "--fetch-all-uri" in myopts
+ ask = "--ask" in myopts
+ tree = "--tree" in myopts
+ verbose = "--verbose" in myopts
+ quiet = "--quiet" in myopts
if pretend or fetchonly:
# make the mtimedb readonly
mtimedb.filename = None
out.eerror("Error: The resume list contains packages that are no longer")
out.eerror(" available to be emerged. Please restart/continue")
out.eerror(" the merge operation manually.")
+ del mtimedb["resume"]
+ mtimedb.commit()
return 1
if show_spinner:
print "\b\b... done!"
portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
return 1
if not retval:
+ mydepgraph.display_problems()
return 1
if "--quiet" not in myopts and "--nodeps" not in myopts:
print "\b\b... done!"
+ display = pretend or \
+ ((ask or tree or verbose) and not (quiet and not ask))
+ if not display:
+ mydepgraph.display_problems()
if "--pretend" not in myopts and \
("--ask" in myopts or "--tree" in myopts or \
phase_retval = exit_status_check(phase_retval)
if phase_retval == os.EX_OK:
# Post phase logic and tasks that have been factored out of
- # ebuild.sh.
+ # ebuild.sh. Call preinst_mask last so that INSTALL_MASK can
+ # can be used to wipe out any gmon.out files created during
+ # previous functions (in case any tools were built with -pg
+ # in CFLAGS).
myargs = [_shell_quote(misc_sh_binary),
- "preinst_bsdflags", "preinst_mask",
+ "preinst_bsdflags",
"preinst_sfperms", "preinst_selinux_labels",
- "preinst_suid_scan"]
+ "preinst_suid_scan", "preinst_mask"]
_doebuild_exit_status_unlink(
mysettings.get("EBUILD_EXIT_STATUS_FILE"))
mysettings["EBUILD_PHASE"] = ""
if trees is None:
global db
trees = db
+ selective = trees[myroot].get("selective", False)
writemsg("ZapDeps -- %s\n" % (use_binaries), 2)
if not reduced or unreduced == ["||"] or dep_eval(reduced):
return []
has_mask = False
if hasattr(mydbapi, "xmatch"):
has_mask = bool(mydbapi.xmatch("match-all", atom))
- if (use_binaries or not has_mask):
+ if (selective or use_binaries or not has_mask):
avail_pkg = best(vardb.match(atom))
if avail_pkg:
avail_slot = "%s:%s" % (dep_getkey(atom),
mymessage = portage.mail.create_message(myfrom, myrecipient, mysubject,
mybody, attachments=items.values())
+
+ def timeout_handler(signum, frame):
+ raise PortageException("Timeout in finalize() for elog system 'mail_summary'")
+ import signal
+ signal.signal(signal.SIGALRM, timeout_handler)
+ # Timeout after one minute in case send_mail() blocks indefinitely.
+ signal.alarm(60)
+
try:
- portage.mail.send_mail(mysettings, mymessage)
+ try:
+ portage.mail.send_mail(mysettings, mymessage)
+ finally:
+ signal.alarm(0)
except PortageException, e:
writemsg("%s\n" % str(e), noiselevel=-1)
def check(self, num, line):
"""Run the check on line and return error if there is one"""
- pass
-
+ if self.re.match(line):
+ return self.error
class EbuildHeader(LineCheck):
"""Ensure ebuilds have proper headers
elif self.method_re.match(line):
self.check_next_line = True
+class EbuildPatches(LineCheck):
+ """Ensure ebuilds use bash arrays for PATCHES to ensure white space safety"""
+ repoman_check_name = 'ebuild.patches'
+ re = re.compile(r'^\s*PATCHES=[^\(]')
+ error = errors.PATCHES_ERROR
class EbuildQuotedA(LineCheck):
"""Ensure ebuilds have no quoting around ${A}"""
_constant_checks = tuple((c() for c in (
EbuildWhitespace, EbuildQuote,
EbuildAssignment, EbuildUselessDodoc,
- EbuildUselessCdS, EbuildNestedDie, EbuildQuotedA)))
+ EbuildUselessCdS, EbuildNestedDie,
+ EbuildPatches, EbuildQuotedA)))
def run_checks(contents, st_mtime):
checks = list(_constant_checks)
READONLY_ASSIGNMENT_ERROR = 'Ebuild contains assignment to read-only variable on line: %d'
MISSING_QUOTES_ERROR = 'Unquoted Variable on line: %d'
NESTED_DIE_ERROR = 'Ebuild calls die in a subshell on line: %d'
+PATCHES_ERROR = 'PATCHES is not a bash array on line: %d'
REDUNDANT_CD_S_ERROR = 'Ebuild has redundant cd ${S} statement on line: %d'