diff options
author | Thomas Sachau <tommy@gentoo.org> | 2016-02-28 13:25:01 +0100 |
---|---|---|
committer | Thomas Sachau <tommy@gentoo.org> | 2016-02-28 13:25:01 +0100 |
commit | fa253ca6f939b075c380e6c208a3283bcbaab0c5 (patch) | |
tree | 17f94ac792c8fe28b4ba04c9e16cd068ce712369 | |
parent | Merge tag 'v2.2.23' into multilib (diff) | |
parent | Bump version, update RELEASE-NOTES (diff) | |
download | portage-fa253ca6.tar.gz portage-fa253ca6.tar.bz2 portage-fa253ca6.zip |
Merge tag 'v2.2.24' into multilib
Version 2.2.24
37 files changed, 291 insertions, 218 deletions
diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 11b18a9c2..fe89e8531 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -1,6 +1,25 @@ Release Notes; upgrade information mainly. Features/major bugfixes are listed in NEWS +portage-2.2.24 +================================== +* Bug Fixes: + - Bug 562964 handle missing cgroup IOError + - Bug 562808 repoman: Set max DESCRIPTION length to 80 + - Bug 563482 emerge(1): document --oneshot caveats + - Bug 563740 calc_depclean: fix AttributeError for + SonameAtom.unevaluated_atom + - Bug 563844 calc_depclean: do not abort for broken soname dependencies + - Bug 563876 BinpkgFetcher._set_returncode: fix ftp _mtime_ handling + - Bug 563546 repoman: check deps of stable ebuilds for unstable + configurations + - Bug 563836 RepoConfigLoader: allow subsitution of variables like ROOT in + repos.conf + - Bug 564222 vardbapi.aux_get: treat cache as valid if mtime is truncated + - Bug 561264 AbstractEbuildProcess: validate cgroup release agent +* Egencache changes for the new git tree changelog generation. + + portage-2.2.23 ================================== * Bug Fixes: diff --git a/bin/binhost-snapshot b/bin/binhost-snapshot index 3a346431e..4130e75ae 100755 --- a/bin/binhost-snapshot +++ b/bin/binhost-snapshot @@ -2,6 +2,7 @@ # Copyright 2010-2014 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 +import argparse import io import os import sys @@ -17,7 +18,6 @@ if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".porta sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym")) import portage portage._internal_caller = True -from portage.util._argparse import ArgumentParser def parse_args(argv): prog_name = os.path.basename(argv[0]) @@ -45,7 +45,7 @@ def parse_args(argv): "write Packages index with\n" + \ " snapshot_uri" - parser = ArgumentParser(usage=usage) + parser = argparse.ArgumentParser(usage=usage) parser.add_argument('--hardlinks', help='create hardlinks (y or n, default is y)', choices=('y', 'n'), diff --git a/bin/cgroup-release-agent b/bin/cgroup-release-agent index 7aa6d56b4..b024e0830 100755 --- a/bin/cgroup-release-agent +++ b/bin/cgroup-release-agent @@ -1,2 +1,2 @@ -#!/bin/bash +#!/bin/sh exec rmdir "/sys/fs/cgroup/portage/${1}" diff --git a/bin/chpathtool.py b/bin/chpathtool.py index 842f1f468..73c7a5f56 100755 --- a/bin/chpathtool.py +++ b/bin/chpathtool.py @@ -7,18 +7,12 @@ doc = """Helper tool for converting installed files to custom prefixes. In other words, eprefixy $D for Gentoo/Prefix.""" __doc__ = doc - +import argparse import io import os import stat import sys -try: - from argparse import ArgumentParser -except ImportError: - ArgumentParser = None - from optparse import OptionParser - CONTENT_ENCODING = 'utf_8' FS_ENCODING = 'utf_8' @@ -152,33 +146,16 @@ def chpath_inplace_symlink(filename, st, old, new): def main(argv): - if ArgumentParser is not None: - parser = ArgumentParser(description=doc) - parser.add_argument('location', default=None, - help='root directory (e.g. $D)') - parser.add_argument('old', default=None, - help='original build prefix (e.g. /)') - parser.add_argument('new', default=None, - help='new install prefix (e.g. $EPREFIX)') - opts = parser.parse_args(argv) - - location, old, new = opts.location, opts.old, opts.new - else: - # Argument parsing compatibility for Python 2.6 using optparse. - parser = OptionParser(description=doc, - usage="usage: %prog [-h] location old new\n\n" + \ - " location: root directory (e.g. $D)\n" + \ - " old: original build prefix (e.g. /)\n" + \ - " new: new install prefix (e.g. $EPREFIX)") - - (opts, args) = parser.parse_args() - - if len(args) != 3: - parser.print_usage() - parser.error("%s: error: expected 3 arguments, got %i" - % (__file__, len(args))) - - location, old, new = args[0:3] + parser = argparse.ArgumentParser(description=doc) + parser.add_argument('location', default=None, + help='root directory (e.g. $D)') + parser.add_argument('old', default=None, + help='original build prefix (e.g. /)') + parser.add_argument('new', default=None, + help='new install prefix (e.g. $EPREFIX)') + opts = parser.parse_args(argv) + + location, old, new = opts.location, opts.old, opts.new is_text_file = IsTextFile() diff --git a/bin/ebuild b/bin/ebuild index ad52ed513..59fced08c 100755 --- a/bin/ebuild +++ b/bin/ebuild @@ -4,6 +4,7 @@ from __future__ import print_function +import argparse import platform import signal import sys @@ -48,13 +49,12 @@ from portage import _shell_quote from portage import _unicode_decode from portage import _unicode_encode from portage.const import VDB_PATH -from portage.util._argparse import ArgumentParser from _emerge.Package import Package from _emerge.RootConfig import RootConfig description = "See the ebuild(1) man page for more info" usage = "Usage: ebuild <ebuild file> <command> [command] ..." -parser = ArgumentParser(description=description, usage=usage) +parser = argparse.ArgumentParser(description=description, usage=usage) force_help = "When used together with the digest or manifest " + \ "command, this option forces regeneration of digests for all " + \ diff --git a/bin/egencache b/bin/egencache index 67fca7303..51d115ade 100755 --- a/bin/egencache +++ b/bin/egencache @@ -5,6 +5,7 @@ # unicode_literals for compat with TextIOWrapper in Python 2 from __future__ import print_function, unicode_literals +import argparse import platform import signal import stat @@ -54,7 +55,6 @@ from portage.const import TIMESTAMP_FORMAT from portage.manifest import guessManifestFileType from portage.package.ebuild._parallel_manifest.ManifestScheduler import ManifestScheduler from portage.util import cmp_sort_key, writemsg_level -from portage.util._argparse import ArgumentParser from portage.util._async.run_main_scheduler import run_main_scheduler from portage.util._eventloop.global_event_loop import global_event_loop from portage import cpv_getkey @@ -81,7 +81,7 @@ if sys.hexversion >= 0x3000000: def parse_args(args): usage = "egencache [options] <action> ... [atom] ..." - parser = ArgumentParser(usage=usage) + parser = argparse.ArgumentParser(usage=usage) actions = parser.add_argument_group('Actions') actions.add_argument("--update", @@ -170,6 +170,15 @@ def parse_args(args): help="output file for use.local.desc data (or '-' for stdout)", dest="uld_output") + uc = parser.add_argument_group('--update-changelogs options') + uc.add_argument("--changelog-reversed", + action="store_true", + help="log commits in reverse order (oldest first)") + uc.add_argument("--changelog-output", + help="output filename for change logs", + dest="changelog_output", + default="ChangeLog") + options, args = parser.parse_known_args(args) if options.jobs: @@ -739,7 +748,7 @@ class _special_filename(_filename_base): return self.file_name < other.file_name class GenChangeLogs(object): - def __init__(self, portdb): + def __init__(self, portdb, changelog_output, changelog_reversed): self.returncode = os.EX_OK self._portdb = portdb self._wrapper = textwrap.TextWrapper( @@ -747,6 +756,8 @@ class GenChangeLogs(object): initial_indent = ' ', subsequent_indent = ' ' ) + self._changelog_output = changelog_output + self._changelog_reversed = changelog_reversed @staticmethod def grab(cmd): @@ -756,7 +767,7 @@ class GenChangeLogs(object): def generate_changelog(self, cp): try: - output = io.open('ChangeLog', + output = io.open(self._changelog_output, mode='w', encoding=_encodings['repo.content'], errors='backslashreplace') except IOError as e: @@ -769,12 +780,16 @@ class GenChangeLogs(object): output.write(textwrap.dedent('''\ # ChangeLog for %s # Copyright 1999-%s Gentoo Foundation; Distributed under the GPL v2 - # $Header: $ + # (auto-generated from git log) ''' % (cp, time.strftime('%Y')))) # now grab all the commits - commits = self.grab(['git', 'rev-list', 'HEAD', '--', '.']).split() + revlist_cmd = ['git', 'rev-list'] + if self._changelog_reversed: + revlist_cmd.append('--reverse') + revlist_cmd.extend(['HEAD', '--', '.']) + commits = self.grab(revlist_cmd).split() for c in commits: # Explaining the arguments: @@ -809,7 +824,7 @@ class GenChangeLogs(object): f = l.split() if f[1] == 'Manifest': pass # XXX: remanifest commits? - elif f[1] == 'ChangeLog': + elif f[1].startswith('ChangeLog'): pass elif f[0].startswith('A'): changed.append(_special_filename("+", f[1])) @@ -1132,7 +1147,9 @@ def egencache_main(args): ret.append(gen_desc.returncode) if options.update_changelogs: - gen_clogs = GenChangeLogs(portdb) + gen_clogs = GenChangeLogs(portdb, + changelog_output=options.changelog_output, + changelog_reversed=options.changelog_reversed) gen_clogs.run() ret.append(gen_clogs.returncode) diff --git a/bin/fixpackages b/bin/fixpackages index 8a0c4448d..70ca9fc90 100755 --- a/bin/fixpackages +++ b/bin/fixpackages @@ -4,6 +4,7 @@ from __future__ import print_function +import argparse import os import sys @@ -14,7 +15,6 @@ import portage portage._internal_caller = True from portage import os from portage.output import EOutput -from portage.util._argparse import ArgumentParser from textwrap import wrap from portage._global_updates import _global_updates mysettings = portage.settings @@ -25,7 +25,7 @@ description = """The fixpackages program performs package move updates on configuration files, installed packages, and binary packages.""" description = " ".join(description.split()) -parser = ArgumentParser(description=description) +parser = argparse.ArgumentParser(description=description) parser.parse_args() if mysettings['ROOT'] != "/": diff --git a/bin/glsa-check b/bin/glsa-check index 94dea7398..84481d849 100755 --- a/bin/glsa-check +++ b/bin/glsa-check @@ -4,6 +4,7 @@ from __future__ import print_function +import argparse import sys import codecs @@ -14,7 +15,6 @@ import portage portage._internal_caller = True from portage import os from portage.output import green, red, nocolor, white -from portage.util._argparse import ArgumentParser __program__ = "glsa-check" __author__ = "Marius Mauch <genone@gentoo.org>" @@ -24,7 +24,7 @@ __version__ = "1.0" epilog = "glsa-list can contain an arbitrary number of GLSA ids," \ " filenames containing GLSAs or the special identifiers" \ " 'all', 'new' and 'affected'" -parser = ArgumentParser(usage=__program__ + " <option> [glsa-list]", +parser = argparse.ArgumentParser(usage=__program__ + " <option> [glsa-list]", epilog=epilog) modes = parser.add_argument_group("Modes") diff --git a/bin/install.py b/bin/install.py index 5bbe97bf2..d3789ed96 100755 --- a/bin/install.py +++ b/bin/install.py @@ -2,6 +2,7 @@ # Copyright 2013-2014 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 +import argparse import os import stat import sys @@ -9,7 +10,6 @@ import subprocess import traceback import portage -from portage.util._argparse import ArgumentParser from portage.util.movefile import _copyxattr from portage.exception import OperationNotSupported @@ -24,7 +24,7 @@ def parse_args(args): Returns: tuple of the Namespace of parsed options, and a list of order parameters """ - parser = ArgumentParser(add_help=False) + parser = argparse.ArgumentParser(add_help=False) parser.add_argument( "-b", diff --git a/bin/portageq b/bin/portageq index 649ee04ee..548d090e0 100755 --- a/bin/portageq +++ b/bin/portageq @@ -4,6 +4,7 @@ from __future__ import print_function, unicode_literals +import argparse import signal import sys # This block ensures that ^C interrupts are handled quietly. @@ -44,7 +45,6 @@ portage._internal_caller = True from portage import os from portage.eapi import eapi_has_repo_deps from portage.util import writemsg, writemsg_stdout -from portage.util._argparse import ArgumentParser portage.proxy.lazyimport.lazyimport(globals(), 're', 'subprocess', @@ -1310,7 +1310,7 @@ def usage(argv): print() print('Pkgcore pquery compatible options:') print() - parser = ArgumentParser(add_help=False, + parser = argparse.ArgumentParser(add_help=False, usage='portageq pquery [options] [atom ...]') add_pquery_arguments(parser) parser.print_help() @@ -1342,7 +1342,7 @@ def main(argv): if nocolor in ('yes', 'true'): portage.output.nocolor() - parser = ArgumentParser(add_help=False) + parser = argparse.ArgumentParser(add_help=False) # used by envvar parser.add_argument("-v", dest="verbose", action="store_true") diff --git a/bin/quickpkg b/bin/quickpkg index 262fda4ab..4f26ee912 100755 --- a/bin/quickpkg +++ b/bin/quickpkg @@ -4,6 +4,7 @@ from __future__ import division, print_function +import argparse import errno import math import signal @@ -26,7 +27,6 @@ xattr = _xattr.xattr from portage.dbapi.vartree import dblink, tar_contents from portage.checksum import perform_md5 from portage._sets import load_default_config, SETPREFIX -from portage.util._argparse import ArgumentParser def quickpkg_atom(options, infos, arg, eout): settings = portage.settings @@ -302,7 +302,7 @@ def quickpkg_main(options, args, eout): if __name__ == "__main__": usage = "quickpkg [options] <list of package atoms or package sets>" - parser = ArgumentParser(usage=usage) + parser = argparse.ArgumentParser(usage=usage) parser.add_argument("--umask", default="0077", help="umask used during package creation (default is 0077)") diff --git a/bin/xattr-helper.py b/bin/xattr-helper.py index 19f25f92d..b5faed044 100755 --- a/bin/xattr-helper.py +++ b/bin/xattr-helper.py @@ -13,12 +13,12 @@ https://en.wikipedia.org/wiki/Extended_file_attributes __doc__ = doc +import argparse import array import os import re import sys -from portage.util._argparse import ArgumentParser from portage.util._xattr import xattr @@ -140,7 +140,7 @@ def restore_xattrs(file_in): def main(argv): - parser = ArgumentParser(description=doc) + parser = argparse.ArgumentParser(description=doc) parser.add_argument('paths', nargs='*', default=[]) actions = parser.add_argument_group('Actions') diff --git a/bin/xpak-helper.py b/bin/xpak-helper.py index c4391cde7..8c965ecda 100755 --- a/bin/xpak-helper.py +++ b/bin/xpak-helper.py @@ -2,11 +2,11 @@ # Copyright 2009-2014 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 +import argparse import sys import portage portage._internal_caller = True from portage import os -from portage.util._argparse import ArgumentParser def command_recompose(args): @@ -46,7 +46,7 @@ def main(argv): usage = "usage: %s COMMAND [args]" % \ os.path.basename(argv[0]) - parser = ArgumentParser(description=description, usage=usage) + parser = argparse.ArgumentParser(description=description, usage=usage) options, args = parser.parse_known_args(argv[1:]) if not args: diff --git a/man/egencache.1 b/man/egencache.1 index abbbdb93c..2465ddf04 100644 --- a/man/egencache.1 +++ b/man/egencache.1 @@ -40,6 +40,16 @@ information about why this is necessary. .br Defaults to /var/cache/edb/dep. .TP +.BR "\-\-changelog\-output=FILENAME" +Specifies the file name used to store autogenerated ChangeLogs inside +the package directories. +.br +Defaults to ChangeLog. +.TP +.BR "\-\-changelog\-reversed" +Reverses the commit order in ChangeLogs. The oldest commits are output +first, the newest last. +.TP .BR "\-\-config\-root=PORTAGE_CONFIGROOT" Location of portage config files. .br diff --git a/man/emerge.1 b/man/emerge.1 index 237fb799a..c03f04471 100644 --- a/man/emerge.1 +++ b/man/emerge.1 @@ -676,6 +676,13 @@ packages that depend on matching packages due to \fB\-\-rebuild\fR. .BR "\-\-oneshot " (\fB\-1\fR) Emerge as normal, but do not add the packages to the world file for later updating. + +\fBWARNING:\fR This option should only be used for packages that are +reachable from the @world package set (those that would not be removed +by \fB\-\-depclean\fR), since dependencies of unreachable packages are +allowed to be broken when satisfying dependencies of other packages. +Broken dependencies of this sort will invalidate assumptions that make +it possible for \fB\-\-deep\fR to be disabled by default. .TP .BR "\-\-onlydeps " (\fB\-o\fR) Only merge (or pretend to merge) the dependencies of the packages diff --git a/pym/_emerge/AbstractEbuildProcess.py b/pym/_emerge/AbstractEbuildProcess.py index 2b5d9c78d..8bd30a640 100644 --- a/pym/_emerge/AbstractEbuildProcess.py +++ b/pym/_emerge/AbstractEbuildProcess.py @@ -96,6 +96,24 @@ class AbstractEbuildProcess(SpawnProcess): with open(os.path.join( cgroup_portage, 'notify_on_release'), 'w') as f: f.write('1') + else: + # Update release_agent if it no longer exists, because + # it refers to a temporary path when portage is updating + # itself. + release_agent = os.path.join( + cgroup_portage, 'release_agent') + try: + with open(release_agent) as f: + release_agent_path = f.readline().rstrip('\n') + except EnvironmentError: + release_agent_path = None + + if (release_agent_path is None or + not os.path.exists(release_agent_path)): + with open(release_agent, 'w') as f: + f.write(os.path.join( + self.settings['PORTAGE_BIN_PATH'], + 'cgroup-release-agent')) cgroup_path = tempfile.mkdtemp(dir=cgroup_portage, prefix='%s:%s.' % (self.settings["CATEGORY"], diff --git a/pym/_emerge/Binpkg.py b/pym/_emerge/Binpkg.py index 7b7ae1759..1c10c6b69 100644 --- a/pym/_emerge/Binpkg.py +++ b/pym/_emerge/Binpkg.py @@ -12,7 +12,7 @@ from _emerge.EbuildMerge import EbuildMerge from _emerge.EbuildBuildDir import EbuildBuildDir from _emerge.SpawnProcess import SpawnProcess from portage.eapi import eapi_exports_replace_vars -from portage.util import ensure_dirs, writemsg +from portage.util import ensure_dirs import portage from portage import os from portage import shutil @@ -21,8 +21,6 @@ from portage import _unicode_decode from portage import _unicode_encode import io import logging -import textwrap -from portage.output import colorize class Binpkg(CompositeTask): @@ -86,16 +84,18 @@ class Binpkg(CompositeTask): elif prefetcher.isAlive() and \ prefetcher.poll() is None: - waiting_msg = ("Fetching '%s' " + \ - "in the background. " + \ - "To view fetch progress, run `tail -f %s` in another terminal.") \ - % (prefetcher.pkg_path, os.path.join( - _emerge.emergelog._emerge_log_dir, "emerge-fetch.log")) - msg_prefix = colorize("GOOD", " * ") - waiting_msg = "".join("%s%s\n" % (msg_prefix, line) \ - for line in textwrap.wrap(waiting_msg, 65)) if not self.background: - writemsg(waiting_msg, noiselevel=-1) + fetch_log = os.path.join( + _emerge.emergelog._emerge_log_dir, 'emerge-fetch.log') + msg = ( + 'Fetching in the background:', + prefetcher.pkg_path, + 'To view fetch progress, run in another terminal:', + 'tail -f %s' % fetch_log, + ) + out = portage.output.EOutput() + for l in msg: + out.einfo(l) self._current_task = prefetcher prefetcher.addExitListener(self._prefetch_exit) diff --git a/pym/_emerge/BinpkgFetcher.py b/pym/_emerge/BinpkgFetcher.py index a7f2d449f..91d24e08a 100644 --- a/pym/_emerge/BinpkgFetcher.py +++ b/pym/_emerge/BinpkgFetcher.py @@ -133,7 +133,7 @@ class BinpkgFetcher(SpawnProcess): if bintree._remote_has_index: remote_mtime = bintree._remotepkgs[ bintree.dbapi._instance_key( - self.pkg.cpv)].get("MTIME") + self.pkg.cpv)].get("_mtime_") if remote_mtime is not None: try: remote_mtime = long(remote_mtime) diff --git a/pym/_emerge/EbuildBuild.py b/pym/_emerge/EbuildBuild.py index 0e9860210..95c14e482 100644 --- a/pym/_emerge/EbuildBuild.py +++ b/pym/_emerge/EbuildBuild.py @@ -17,10 +17,8 @@ from _emerge.EbuildBuildDir import EbuildBuildDir from _emerge.MiscFunctionsProcess import MiscFunctionsProcess from _emerge.TaskSequence import TaskSequence -from portage.util import writemsg import portage from portage import _encodings, _unicode_decode, _unicode_encode, os -from portage.output import colorize from portage.package.ebuild.digestcheck import digestcheck from portage.package.ebuild.digestgen import digestgen from portage.package.ebuild.doebuild import _check_temp_dir @@ -77,16 +75,17 @@ class EbuildBuild(CompositeTask): elif prefetcher.isAlive() and \ prefetcher.poll() is None: - waiting_msg = "Fetching files " + \ - "in the background. " + \ - "To view fetch progress, run `tail -f %s` in another terminal." \ - % (os.path.join(_emerge.emergelog._emerge_log_dir, "emerge-fetch.log")) - msg_prefix = colorize("GOOD", " * ") - from textwrap import wrap - waiting_msg = "".join("%s%s\n" % (msg_prefix, line) \ - for line in wrap(waiting_msg, 65)) if not self.background: - writemsg(waiting_msg, noiselevel=-1) + fetch_log = os.path.join( + _emerge.emergelog._emerge_log_dir, 'emerge-fetch.log') + msg = ( + 'Fetching files in the background.', + 'To view fetch progress, run in another terminal:', + 'tail -f %s' % fetch_log, + ) + out = portage.output.EOutput() + for l in msg: + out.einfo(l) self._current_task = prefetcher prefetcher.addExitListener(self._prefetch_exit) diff --git a/pym/_emerge/SpawnProcess.py b/pym/_emerge/SpawnProcess.py index 15d3dc5cf..5ab2e67d1 100644 --- a/pym/_emerge/SpawnProcess.py +++ b/pym/_emerge/SpawnProcess.py @@ -185,8 +185,8 @@ class SpawnProcess(SubProcess): try: with open(os.path.join(cgroup, 'cgroup.procs'), 'r') as f: return [int(p) for p in f.read().split()] - except OSError: - # cgroup removed already? + except EnvironmentError: + # removed by cgroup-release-agent return [] def kill_all(pids, sig): diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py index 757fc99b4..074000221 100644 --- a/pym/_emerge/actions.py +++ b/pym/_emerge/actions.py @@ -699,35 +699,49 @@ def calc_depclean(settings, trees, ldpath_mtimes, protected_set = InternalPackageSet() protected_set_name = '____depclean_protected_set____' required_sets[protected_set_name] = protected_set - system_set = psets["system"] + set_error = False set_atoms = {} for k in ("profile", "system", "selected"): try: set_atoms[k] = root_config.setconfig.getSetAtoms(k) - except portage.exception.PackageSetNotFound: + except portage.exception.PackageSetNotFound as e: # A nested set could not be resolved, so ignore nested sets. set_atoms[k] = root_config.sets[k].getAtoms() + writemsg_level(_("!!! The set '%s' " + "contains a non-existent set named '%s'.\n") % + (k, e), level=logging.ERROR, noiselevel=-1) + set_error = True + + # Support @profile as an alternative to @system. + if not (set_atoms["system"] or set_atoms["profile"]): + writemsg_level(_("!!! You have no system list.\n"), + level=logging.WARNING, noiselevel=-1) - if (not set_atoms["system"] or - not (set_atoms["selected"] or set_atoms["profile"])): + if not set_atoms["selected"]: + writemsg_level(_("!!! You have no world file.\n"), + level=logging.WARNING, noiselevel=-1) - if not set_atoms["system"]: - writemsg_level("!!! You have no system list.\n", + # Suppress world file warnings unless @world is completely empty, + # since having an empty world file can be a valid state. + try: + world_atoms = bool(root_config.setconfig.getSetAtoms('world')) + except portage.exception.PackageSetNotFound as e: + writemsg_level(_("!!! The set '%s' " + "contains a non-existent set named '%s'.\n") % + ("world", e), level=logging.ERROR, noiselevel=-1) + set_error = True + else: + if not world_atoms: + writemsg_level(_("!!! Your @world set is empty.\n"), level=logging.ERROR, noiselevel=-1) + set_error = True - # Skip this warning if @profile is non-empty, in order to - # support using @profile as an alternative to @selected - # for building a stage 4. - if not (set_atoms["selected"] or set_atoms["profile"]): - writemsg_level("!!! You have no world file.\n", - level=logging.WARNING, noiselevel=-1) - - writemsg_level("!!! Proceeding is likely to " + \ - "break your installation.\n", - level=logging.WARNING, noiselevel=-1) - if "--pretend" not in myopts: - countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean") + if set_error: + writemsg_level(_("!!! Aborting due to set configuration " + "errors displayed above.\n"), + level=logging.ERROR, noiselevel=-1) + return 1, [], False, 0 if action == "depclean": emergelog(xterm_titles, " >>> depclean") @@ -849,11 +863,31 @@ def calc_depclean(settings, trees, ldpath_mtimes, def unresolved_deps(): + soname_deps = set() unresolvable = set() for dep in resolver._dynamic_config._initially_unsatisfied_deps: if isinstance(dep.parent, Package) and \ (dep.priority > UnmergeDepPriority.SOFT): - unresolvable.add((dep.atom, dep.parent.cpv)) + if dep.atom.soname: + soname_deps.add((dep.atom, dep.parent.cpv)) + else: + unresolvable.add((dep.atom, dep.parent.cpv)) + + if soname_deps: + # Generally, broken soname dependencies can safely be + # suppressed by a REQUIRES_EXCLUDE setting in the ebuild, + # so they should only trigger a warning message. + prefix = warn(" * ") + msg = [] + msg.append("Broken soname dependencies found:") + msg.append("") + for atom, parent in soname_deps: + msg.append(" %s required by:" % (atom,)) + msg.append(" %s" % (parent,)) + msg.append("") + + writemsg_level("".join("%s%s\n" % (prefix, line) for line in msg), + level=logging.WARNING, noiselevel=-1) if not unresolvable: return False @@ -871,7 +905,7 @@ def calc_depclean(settings, trees, ldpath_mtimes, msg.append("the following required packages not being installed:") msg.append("") for atom, parent in unresolvable: - if atom != atom.unevaluated_atom and \ + if atom.package and atom != atom.unevaluated_atom and \ vardb.match(_unicode(atom)): msg.append(" %s (%s) pulled in by:" % (atom.unevaluated_atom, atom)) diff --git a/pym/_emerge/main.py b/pym/_emerge/main.py index b69aa241a..e75bb0a0d 100644 --- a/pym/_emerge/main.py +++ b/pym/_emerge/main.py @@ -3,6 +3,7 @@ from __future__ import print_function +import argparse import locale import platform import sys @@ -19,7 +20,6 @@ portage.proxy.lazyimport.lazyimport(globals(), '_emerge.is_valid_package_atom:insert_category_into_atom' ) from portage import os -from portage.util._argparse import ArgumentParser from portage.sync import _SUBMODULE_PATH_MAP if sys.hexversion >= 0x3000000: @@ -705,7 +705,7 @@ def parse_opts(tmpcmdline, silent=False): }, } - parser = ArgumentParser(add_help=False) + parser = argparse.ArgumentParser(add_help=False) for action_opt in actions: parser.add_argument("--" + action_opt, action="store_true", diff --git a/pym/portage/_emirrordist/main.py b/pym/portage/_emirrordist/main.py index ce92c2aea..7378ac7b3 100644 --- a/pym/portage/_emirrordist/main.py +++ b/pym/portage/_emirrordist/main.py @@ -1,13 +1,13 @@ # Copyright 2013-2014 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 +import argparse import logging import sys import portage from portage import os from portage.util import normalize_path, writemsg_level, _recursive_file_list -from portage.util._argparse import ArgumentParser from portage.util._async.run_main_scheduler import run_main_scheduler from portage.util._async.SchedulerInterface import SchedulerInterface from portage.util._eventloop.global_event_loop import global_event_loop @@ -202,7 +202,7 @@ def parse_args(args): description = "emirrordist - a fetch tool for mirroring " \ "of package distfiles" usage = "emirrordist [options] <action>" - parser = ArgumentParser(description=description, usage=usage) + parser = argparse.ArgumentParser(description=description, usage=usage) actions = parser.add_argument_group('Actions') actions.add_argument("--version", diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 5ba8d9d34..e7effca32 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -728,7 +728,13 @@ class vardbapi(dbapi): if pkg_data: cache_mtime, metadata = pkg_data if isinstance(cache_mtime, float): - cache_valid = cache_mtime == mydir_stat.st_mtime + if cache_mtime == mydir_stat.st_mtime: + cache_valid = True + + # Handle truncated mtime in order to avoid cache + # invalidation for livecd squashfs (bug 564222). + elif long(cache_mtime) == mydir_stat.st_mtime: + cache_valid = True else: # Cache may contain integer mtime. cache_valid = cache_mtime == mydir_stat[stat.ST_MTIME] diff --git a/pym/portage/emaint/main.py b/pym/portage/emaint/main.py index e71efe868..65e3545b4 100644 --- a/pym/portage/emaint/main.py +++ b/pym/portage/emaint/main.py @@ -3,7 +3,7 @@ from __future__ import print_function - +import argparse import sys import textwrap @@ -12,7 +12,6 @@ from portage import os from portage.module import Modules from portage.progress import ProgressBar from portage.emaint.defaults import DEFAULT_OPTIONS -from portage.util._argparse import ArgumentParser class OptionItem(object): """class to hold module ArgumentParser options data @@ -169,8 +168,7 @@ def emaint_main(myargv): module_names = module_controller.module_names[:] module_names.insert(0, "all") - - parser = ArgumentParser(usage=usage(module_controller)) + parser = argparse.ArgumentParser(usage=usage(module_controller)) # add default options parser_options = [] for opt in DEFAULT_OPTIONS: diff --git a/pym/portage/package/ebuild/_config/KeywordsManager.py b/pym/portage/package/ebuild/_config/KeywordsManager.py index 72e24b961..a4ffb623e 100644 --- a/pym/portage/package/ebuild/_config/KeywordsManager.py +++ b/pym/portage/package/ebuild/_config/KeywordsManager.py @@ -112,29 +112,18 @@ class KeywordsManager(object): if self._getMissingKeywords(pkg, pgroups, mygroups): return False - if pkg.cpv._settings.local_config: - # If replacing all keywords with unstable variants would mask the - # package, then it's considered stable. - unstable = [] - for kw in mygroups: - if kw[:1] != "~": - kw = "~" + kw - unstable.append(kw) - - return bool(self._getMissingKeywords(pkg, pgroups, set(unstable))) - else: - # For repoman, if the package has an effective stable keyword that - # intersects with the effective ACCEPT_KEYWORDS for the current - # profile, then consider it stable. - for kw in pgroups: - if kw[:1] != "~": - if kw in mygroups or '*' in mygroups: - return True - if kw == '*': - for x in mygroups: - if x[:1] != "~": - return True - return False + # If replacing all keywords with unstable variants would mask the + # package, then it's considered stable for the purposes of + # use.stable.mask/force interpretation. For unstable configurations, + # this guarantees that the effective use.force/mask settings for a + # particular ebuild do not change when that ebuild is stabilized. + unstable = [] + for kw in mygroups: + if kw[:1] != "~": + kw = "~" + kw + unstable.append(kw) + + return bool(self._getMissingKeywords(pkg, pgroups, set(unstable))) def getMissingKeywords(self, cpv, diff --git a/pym/portage/repository/config.py b/pym/portage/repository/config.py index a90a994c8..1060bc7c9 100644 --- a/pym/portage/repository/config.py +++ b/pym/portage/repository/config.py @@ -620,7 +620,12 @@ class RepoConfigLoader(object): treemap = {} ignored_map = {} ignored_location_map = {} - default_opts = {} + default_opts = { + "EPREFIX" : settings["EPREFIX"], + "EROOT" : settings["EROOT"], + "PORTAGE_CONFIGROOT" : settings["PORTAGE_CONFIGROOT"], + "ROOT" : settings["ROOT"], + } if "PORTAGE_REPOSITORIES" in settings: portdir = "" diff --git a/pym/portage/sync/controller.py b/pym/portage/sync/controller.py index 159b9c094..e8132c2ba 100644 --- a/pym/portage/sync/controller.py +++ b/pym/portage/sync/controller.py @@ -13,7 +13,6 @@ import portage from portage import os from portage.progress import ProgressBar #from portage.emaint.defaults import DEFAULT_OPTIONS -#from portage.util._argparse import ArgumentParser from portage.util import writemsg, writemsg_level from portage.output import create_color_func good = create_color_func("GOOD") diff --git a/pym/portage/tests/__init__.py b/pym/portage/tests/__init__.py index 708dd5934..bf681c47e 100644 --- a/pym/portage/tests/__init__.py +++ b/pym/portage/tests/__init__.py @@ -4,6 +4,7 @@ from __future__ import print_function +import argparse import sys import time import unittest @@ -27,7 +28,6 @@ from portage import _encodings from portage import _unicode_decode from portage.const import (EPREFIX, GLOBAL_CONFIG_PATH, PORTAGE_BASE_PATH, PORTAGE_BIN_PATH) -from portage.util._argparse import ArgumentParser if portage._not_installed: @@ -48,7 +48,7 @@ def main(): basedir = os.path.dirname(os.path.realpath(__file__)) usage = "usage: %s [options] [tests to run]" % os.path.basename(sys.argv[0]) - parser = ArgumentParser(usage=usage) + parser = argparse.ArgumentParser(usage=usage) parser.add_argument("-l", "--list", help="list all tests", action="store_true", dest="list_tests") options, args = parser.parse_known_args(args=sys.argv) diff --git a/pym/portage/tests/resolver/test_depclean.py b/pym/portage/tests/resolver/test_depclean.py index 42350be8b..f3c4c638c 100644 --- a/pym/portage/tests/resolver/test_depclean.py +++ b/pym/portage/tests/resolver/test_depclean.py @@ -165,6 +165,9 @@ class DepcleanWithExcludeTestCase(TestCase): "dev-libs/B-1": { "RDEPEND": "dev-libs/A" }, } + # depclean asserts non-empty @world set + world = ["non-empty/world-set"] + test_cases = ( #Without --exclude. ResolverPlaygroundTestCase( @@ -196,7 +199,7 @@ class DepcleanWithExcludeTestCase(TestCase): cleanlist=[]), ) - playground = ResolverPlayground(installed=installed) + playground = ResolverPlayground(installed=installed, world=world) try: for test_case in test_cases: playground.run_TestCase(test_case) @@ -253,6 +256,9 @@ class DepcleanAndWildcardsTestCase(TestCase): "dev-libs/B-1": {}, } + # depclean asserts non-empty @world set + world = ["non-empty/world-set"] + test_cases = ( ResolverPlaygroundTestCase( ["*/*"], @@ -276,7 +282,7 @@ class DepcleanAndWildcardsTestCase(TestCase): cleanlist=[]), ) - playground = ResolverPlayground(installed=installed) + playground = ResolverPlayground(installed=installed, world=world) try: for test_case in test_cases: playground.run_TestCase(test_case) diff --git a/pym/portage/util/_argparse.py b/pym/portage/util/_argparse.py deleted file mode 100644 index 6ca785235..000000000 --- a/pym/portage/util/_argparse.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2013 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 - -__all__ = ['ArgumentParser'] - -try: - from argparse import ArgumentParser -except ImportError: - # Compatibility with Python 2.6 and 3.1 - from optparse import OptionGroup, OptionParser - - from portage.localization import _ - - class ArgumentParser(object): - def __init__(self, **kwargs): - add_help = kwargs.pop("add_help", None) - if add_help is not None: - kwargs["add_help_option"] = add_help - parser = OptionParser(**kwargs) - self._parser = parser - self.add_argument = parser.add_option - self.print_help = parser.print_help - self.error = parser.error - - def add_argument_group(self, title=None, **kwargs): - optiongroup = OptionGroup(self._parser, title, **kwargs) - self._parser.add_option_group(optiongroup) - return _ArgumentGroup(optiongroup) - - def parse_known_args(self, args=None, namespace=None): - return self._parser.parse_args(args, namespace) - - def parse_args(self, args=None, namespace=None): - args, argv = self.parse_known_args(args, namespace) - if argv: - msg = _('unrecognized arguments: %s') - self.error(msg % ' '.join(argv)) - return args - - class _ArgumentGroup(object): - def __init__(self, optiongroup): - self.add_argument = optiongroup.add_option diff --git a/pym/repoman/argparser.py b/pym/repoman/argparser.py index 0f34ed01c..2d56a87e6 100644 --- a/pym/repoman/argparser.py +++ b/pym/repoman/argparser.py @@ -4,6 +4,7 @@ """This module contains functions used in Repoman to parse CLI arguments.""" +import argparse import logging import sys @@ -12,7 +13,6 @@ from repoman._portage import portage from portage import _unicode_decode from portage import util -from portage.util._argparse import ArgumentParser def parse_args(argv, qahelp, repoman_default_opts): @@ -47,7 +47,7 @@ def parse_args(argv, qahelp, repoman_default_opts): output_keys = sorted(output_choices) - parser = ArgumentParser( + parser = argparse.ArgumentParser( usage="repoman [options] [mode]", description="Modes: %s" % " | ".join(mode_keys), epilog="For more help consult the man page.") diff --git a/pym/repoman/checks/ebuilds/checks.py b/pym/repoman/checks/ebuilds/checks.py index 245ab2b01..a00d518c0 100644 --- a/pym/repoman/checks/ebuilds/checks.py +++ b/pym/repoman/checks/ebuilds/checks.py @@ -408,7 +408,8 @@ class InheritDeprecated(LineCheck): repoman_check_name = 'inherit.deprecated' # deprecated eclass : new eclass (False if no new eclass) - deprecated_classes = { + deprecated_eclasses = { + "base": False, "bash-completion": "bash-completion-r1", "boost-utils": False, "distutils": "distutils-r1", @@ -436,7 +437,7 @@ class InheritDeprecated(LineCheck): return for eclass in direct_inherits: - replacement = self.deprecated_classes.get(eclass) + replacement = self.deprecated_eclasses.get(eclass) if replacement is None: pass elif replacement is False: diff --git a/pym/repoman/qa_data.py b/pym/repoman/qa_data.py index dddfb98ba..df9b8362b 100644 --- a/pym/repoman/qa_data.py +++ b/pym/repoman/qa_data.py @@ -7,8 +7,7 @@ from _emerge.Package import Package # import our initialized portage instance from repoman._portage import portage -# 14 is the length of DESCRIPTION="" -max_desc_len = 100 +max_desc_len = 80 allowed_filename_chars = "a-zA-Z0-9._-+:" qahelp = { diff --git a/pym/repoman/scanner.py b/pym/repoman/scanner.py index df46144e2..9e5a313cd 100644 --- a/pym/repoman/scanner.py +++ b/pym/repoman/scanner.py @@ -379,14 +379,24 @@ class Scanner(object): else: arches.add((keyword, arch, (arch, keyword))) else: + # For ebuilds with stable keywords, check if the + # dependencies are satisfiable for unstable + # configurations, since use.stable.mask is not + # applied for unstable configurations (see bug + # 563546). if keyword == "*": for expanded_arch in self.profiles: if expanded_arch == "**": continue arches.add( (keyword, expanded_arch, (expanded_arch,))) + arches.add( + (keyword, expanded_arch, + (expanded_arch, "~" + expanded_arch))) else: arches.add((keyword, keyword, (keyword,))) + arches.add((keyword, keyword, + (keyword, "~" + keyword))) if not arches: # Use an empty profile for checking dependencies of # packages that have empty KEYWORDS. @@ -15,8 +15,10 @@ from __future__ import print_function import argparse import os -import sys +import shutil import subprocess +import sys +import tempfile # These are the versions we fully support and require to pass tests. @@ -91,6 +93,8 @@ $ %(prog)s pym/portage/tests/xpak/test_decodeint.py description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, epilog=epilog) + parser.add_argument('--keep-temp', default=False, action='store_true', + help='Do not delete the temporary directory when exiting') parser.add_argument('--color', type=str, default=None, help='Whether to use colorized output (default is auto)') parser.add_argument('--python-versions', action='append', @@ -116,20 +120,34 @@ def main(argv): else: pyversions.extend(ver.split()) - # Actually test those versions now. - statuses = [] - for ver in pyversions: - prog = get_python_executable(ver) - cmd = [prog, '-b', '-Wd', 'pym/portage/tests/runTests.py'] + args - if os.access(prog, os.X_OK): - print('%sTesting with Python %s...%s' % - (colors.GOOD, ver, colors.NORMAL)) - statuses.append(subprocess.call(cmd)) - elif not ignore_missing: - print('%sCould not find requested Python %s%s' % - (colors.BAD, ver, colors.NORMAL)) - statuses.append(1) - print() + tempdir = None + try: + # Set up a single tempdir for all the tests to use. + # This way we know the tests won't leak things on us. + tempdir = tempfile.mkdtemp(prefix='portage.runtests.') + os.environ['TMPDIR'] = tempdir + + # Actually test those versions now. + statuses = [] + for ver in pyversions: + prog = get_python_executable(ver) + cmd = [prog, '-b', '-Wd', 'pym/portage/tests/runTests.py'] + args + if os.access(prog, os.X_OK): + print('%sTesting with Python %s...%s' % + (colors.GOOD, ver, colors.NORMAL)) + statuses.append(subprocess.call(cmd)) + elif not ignore_missing: + print('%sCould not find requested Python %s%s' % + (colors.BAD, ver, colors.NORMAL)) + statuses.append(1) + print() + finally: + if tempdir is not None: + if opts.keep_temp: + print('Temporary directory left behind:\n%s' % tempdir) + else: + # Nuke our tempdir and anything that might be under it. + shutil.rmtree(tempdir, True) # Then summarize it all. print('\nSummary:\n') @@ -2,6 +2,8 @@ # Copyright 1998-2014 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 +from __future__ import print_function + from distutils.core import setup, Command from distutils.command.build import build from distutils.command.build_scripts import build_scripts @@ -250,9 +252,10 @@ class x_build_scripts(build_scripts): class x_clean(clean): """ clean extended for doc & post-test cleaning """ - def clean_docs(self): + @staticmethod + def clean_docs(): def get_doc_outfiles(): - for dirpath, dirnames, filenames in os.walk('doc'): + for dirpath, _dirnames, filenames in os.walk('doc'): for f in filenames: if f.endswith('.docbook') or f == 'custom.xsl': pass @@ -367,7 +370,7 @@ class x_install(install): 'package': self.distribution.get_name(), 'version': self.distribution.get_version(), } - for key, default in self.paths: + for key, _default in self.paths: new_paths[key] = subst_vars(getattr(self, key), new_paths) setattr(self, key, new_paths[key]) self.subst_paths = new_paths @@ -556,7 +559,7 @@ class build_tests(x_build_scripts_custom): # create $build_lib/../.portage_not_installed # to enable proper paths in tests - with open(os.path.join(self.top_dir, '.portage_not_installed'), 'w') as f: + with open(os.path.join(self.top_dir, '.portage_not_installed'), 'w'): pass @@ -581,13 +584,13 @@ class test(Command): def find_packages(): - for dirpath, dirnames, filenames in os.walk('pym'): + for dirpath, _dirnames, filenames in os.walk('pym'): if '__init__.py' in filenames: yield os.path.relpath(dirpath, 'pym') def find_scripts(): - for dirpath, dirnames, filenames in os.walk('bin'): + for dirpath, _dirnames, filenames in os.walk('bin'): for f in filenames: if f not in ['deprecated-path']: yield os.path.join(dirpath, f) @@ -598,10 +601,10 @@ def get_manpages(): if linguas is not None: linguas = linguas.split() - for dirpath, dirnames, filenames in os.walk('man'): + for dirpath, _dirnames, filenames in os.walk('man'): groups = collections.defaultdict(list) for f in filenames: - fn, suffix = f.rsplit('.', 1) + _fn, suffix = f.rsplit('.', 1) groups[suffix].append(os.path.join(dirpath, f)) topdir = dirpath[len('man/'):] @@ -612,7 +615,7 @@ def get_manpages(): setup( name = 'portage', - version = '2.2.23', + version = '2.2.24', url = 'https://wiki.gentoo.org/wiki/Project:Portage', author = 'Gentoo Portage Development Team', author_email = 'dev-portage@gentoo.org', |