From: "Fabian Groffen" <grobian@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/portage:prefix commit in: /
Date: Thu, 18 Feb 2016 19:35:59 +0000 (UTC) [thread overview]
Message-ID: <1455824085.ac7a15e255d0c239fb52aeb3df160378518aa496.grobian@gentoo> (raw)
commit: ac7a15e255d0c239fb52aeb3df160378518aa496
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Thu Feb 18 19:34:45 2016 +0000
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Thu Feb 18 19:34:45 2016 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=ac7a15e2
Merge remote-tracking branch 'overlays-gentoo-org/master' into prefix
.travis.yml | 1 +
NEWS | 17 +
README | 10 +-
RELEASE-NOTES | 133 +
bin/binhost-snapshot | 4 +-
bin/cgroup-release-agent | 2 +
bin/{ebuild-ipc => chmod-lite} | 8 +-
bin/chmod-lite.py | 30 +
bin/chpathtool.py | 45 +-
bin/dohtml.py | 47 +-
bin/eapi.sh | 8 +
bin/ebuild | 24 +-
bin/ebuild.sh | 68 +-
bin/egencache | 200 +-
bin/fixpackages | 4 +-
bin/glsa-check | 4 +-
bin/install-qa-check.d/60openrc | 2 +-
bin/install.py | 4 +-
bin/isolated-functions.sh | 12 +-
bin/misc-functions.sh | 19 +-
bin/phase-functions.sh | 42 +
bin/phase-helpers.sh | 97 +-
bin/portageq | 22 +-
bin/quickpkg | 16 +-
bin/repoman | 3161 +-------------------
bin/save-ebuild-env.sh | 11 +-
bin/socks5-server.py | 9 +-
bin/xattr-helper.py | 15 +-
bin/xpak-helper.py | 4 +-
cnf/make.globals | 2 +-
cnf/sets/portage.conf | 2 +-
doc/qa.docbook | 3 +-
man/ebuild.5 | 13 +-
man/egencache.1 | 20 +-
man/emerge.1 | 16 +-
man/emirrordist.1 | 10 +-
man/make.conf.5 | 49 +-
man/portage.5 | 18 +-
man/repoman.1 | 5 +-
misc/emerge-delta-webrsync | 2 +-
pym/_emerge/AbstractEbuildProcess.py | 41 +-
pym/_emerge/Binpkg.py | 24 +-
pym/_emerge/BinpkgFetcher.py | 9 +-
pym/_emerge/BlockerDB.py | 5 +-
pym/_emerge/EbuildBuild.py | 21 +-
pym/_emerge/PackageVirtualDbapi.py | 4 +-
pym/_emerge/Scheduler.py | 40 +-
pym/_emerge/SpawnProcess.py | 41 +-
pym/_emerge/UserQuery.py | 15 +-
pym/_emerge/actions.py | 145 +-
pym/_emerge/chk_updated_cfg_files.py | 8 +-
pym/_emerge/depgraph.py | 111 +-
pym/_emerge/main.py | 31 +-
pym/_emerge/resolver/circular_dependency.py | 21 +-
pym/_emerge/resolver/slot_collision.py | 11 +-
pym/_emerge/search.py | 3 +-
pym/portage/_emirrordist/Config.py | 10 +-
pym/portage/_emirrordist/main.py | 27 +-
pym/portage/_legacy_globals.py | 2 +-
pym/portage/_sets/__init__.py | 4 +
pym/portage/cache/anydbm.py | 3 +
pym/portage/cache/flat_hash.py | 5 +
pym/portage/cache/sqlite.py | 9 +-
pym/portage/cache/template.py | 61 +-
pym/portage/checksum.py | 4 +-
pym/portage/const.py | 4 +-
pym/portage/data.py | 2 +-
pym/portage/dbapi/IndexedPortdb.py | 4 +-
pym/portage/dbapi/IndexedVardb.py | 6 +-
pym/portage/dbapi/__init__.py | 27 +-
pym/portage/dbapi/bintree.py | 6 +-
pym/portage/dbapi/porttree.py | 44 +-
pym/portage/dbapi/vartree.py | 22 +-
pym/portage/dbapi/virtual.py | 12 +-
pym/portage/dep/__init__.py | 7 +-
pym/portage/dep/dep_check.py | 6 +-
pym/portage/eapi.py | 11 +-
pym/portage/elog/mod_save.py | 3 +-
pym/portage/emaint/main.py | 6 +-
pym/portage/emaint/modules/merges/__init__.py | 2 +-
pym/portage/emaint/modules/sync/sync.py | 191 +-
pym/portage/exception.py | 5 +-
pym/portage/manifest.py | 61 +
pym/portage/news.py | 2 +-
.../package/ebuild/_config/KeywordsManager.py | 35 +-
.../package/ebuild/_config/LicenseManager.py | 4 +-
.../package/ebuild/_config/special_env_vars.py | 2 +-
pym/portage/package/ebuild/config.py | 64 +-
pym/portage/package/ebuild/doebuild.py | 35 +-
pym/portage/package/ebuild/fetch.py | 9 +-
pym/portage/repository/config.py | 83 +-
pym/portage/sync/__init__.py | 20 +-
pym/portage/sync/controller.py | 90 +-
pym/portage/sync/modules/cvs/__init__.py | 5 +-
pym/portage/sync/modules/cvs/cvs.py | 2 +-
pym/portage/sync/modules/git/__init__.py | 1 +
pym/portage/sync/modules/git/git.py | 31 +-
pym/portage/sync/modules/rsync/__init__.py | 4 +
pym/portage/sync/modules/rsync/rsync.py | 34 +-
pym/portage/sync/modules/svn/__init__.py | 1 +
pym/portage/sync/modules/webrsync/__init__.py | 1 +
pym/portage/sync/syncbase.py | 2 +-
pym/portage/tests/__init__.py | 4 +-
pym/portage/tests/dbapi/test_portdb_cache.py | 3 +-
pym/portage/tests/dep/test_match_from_list.py | 21 +-
pym/portage/tests/ebuild/test_config.py | 4 +-
pym/portage/tests/ebuild/test_doebuild_fd_pipes.py | 37 +-
pym/portage/tests/ebuild/test_doebuild_spawn.py | 3 +-
pym/portage/tests/ebuild/test_ipc_daemon.py | 3 +-
pym/portage/tests/emerge/test_config_protect.py | 3 +-
pym/portage/tests/emerge/test_emerge_slot_abi.py | 3 +-
pym/portage/tests/emerge/test_simple.py | 3 +-
pym/portage/tests/repoman/test_simple.py | 9 +-
.../tests/resolver/test_autounmask_parent.py | 43 +
pym/portage/tests/resolver/test_depclean.py | 10 +-
pym/portage/tests/sync/test_sync_local.py | 82 +-
pym/portage/tests/util/test_xattr.py | 178 ++
pym/portage/util/__init__.py | 97 +-
pym/portage/util/_argparse.py | 42 -
pym/portage/util/_async/AsyncFunction.py | 70 +
pym/portage/util/_xattr.py | 228 ++
pym/portage/util/locale.py | 142 +
pym/portage/util/movefile.py | 100 +-
pym/portage/util/xattr.py | 20 -
pym/portage/xml/metadata.py | 3 +
pym/repoman/_portage.py | 25 +
pym/repoman/_subprocess.py | 83 +
pym/repoman/_xml.py | 106 +
pym/repoman/actions.py | 836 ++++++
pym/repoman/argparser.py | 225 ++
pym/repoman/check_missingslot.py | 7 +-
pym/repoman/{ => checks}/__init__.py | 0
pym/repoman/{ => checks/directories}/__init__.py | 0
pym/repoman/checks/directories/files.py | 81 +
pym/repoman/{ => checks/ebuilds}/__init__.py | 0
pym/repoman/{ => checks/ebuilds}/checks.py | 219 +-
.../{ => checks/ebuilds/eclasses}/__init__.py | 0
pym/repoman/checks/ebuilds/eclasses/live.py | 39 +
pym/repoman/checks/ebuilds/eclasses/ruby.py | 32 +
pym/repoman/checks/ebuilds/errors.py | 49 +
pym/repoman/checks/ebuilds/fetches.py | 135 +
pym/repoman/checks/ebuilds/isebuild.py | 71 +
pym/repoman/checks/ebuilds/keywords.py | 122 +
pym/repoman/checks/ebuilds/manifests.py | 102 +
pym/repoman/checks/ebuilds/misc.py | 57 +
pym/repoman/checks/ebuilds/pkgmetadata.py | 177 ++
pym/repoman/checks/ebuilds/thirdpartymirrors.py | 39 +
pym/repoman/checks/ebuilds/use_flags.py | 90 +
.../{ => checks/ebuilds/variables}/__init__.py | 0
.../checks/ebuilds/variables/description.py | 32 +
pym/repoman/checks/ebuilds/variables/eapi.py | 44 +
pym/repoman/checks/ebuilds/variables/license.py | 47 +
pym/repoman/checks/ebuilds/variables/restrict.py | 41 +
pym/repoman/{ => checks/herds}/__init__.py | 0
pym/repoman/{ => checks/herds}/herdbase.py | 28 +-
pym/repoman/checks/herds/metadata.py | 26 +
pym/repoman/copyrights.py | 120 +
pym/repoman/ebuild.py | 29 +
pym/repoman/errors.py | 49 +-
pym/repoman/gpg.py | 82 +
pym/repoman/main.py | 169 ++
pym/repoman/metadata.py | 153 +
pym/repoman/{ => modules}/__init__.py | 0
pym/repoman/{ => modules/commit}/__init__.py | 0
pym/repoman/modules/commit/repochecks.py | 35 +
pym/repoman/{ => modules/fix}/__init__.py | 0
pym/repoman/{ => modules/full}/__init__.py | 0
pym/repoman/{ => modules/manifest}/__init__.py | 0
pym/repoman/{ => modules/scan}/__init__.py | 0
pym/repoman/profile.py | 87 +
pym/repoman/qa_data.py | 439 +++
pym/repoman/qa_tracker.py | 45 +
pym/repoman/repos.py | 307 ++
pym/repoman/scan.py | 172 ++
pym/repoman/scanner.py | 755 +++++
pym/repoman/utilities.py | 572 +---
pym/repoman/{ => vcs}/__init__.py | 0
pym/repoman/vcs/vcs.py | 287 ++
pym/repoman/vcs/vcsstatus.py | 114 +
runtests | 50 +-
setup.py | 21 +-
181 files changed, 8297 insertions(+), 4668 deletions(-)
diff --cc bin/ebuild
index 1e9dd4b,1f99177..1692a92
--- a/bin/ebuild
+++ b/bin/ebuild
@@@ -1,5 -1,5 +1,5 @@@
-#!/usr/bin/python -bO
+#!@PREFIX_PORTAGE_PYTHON@ -bO
- # Copyright 1999-2014 Gentoo Foundation
+ # Copyright 1999-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
from __future__ import print_function
diff --cc bin/egencache
index b26fd8e,7e3387e..843f374
--- a/bin/egencache
+++ b/bin/egencache
@@@ -1,5 -1,5 +1,5 @@@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
- # Copyright 2009-2014 Gentoo Foundation
+ # Copyright 2009-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# unicode_literals for compat with TextIOWrapper in Python 2
diff --cc bin/isolated-functions.sh
index a37130c,e320f71..5126bf9
--- a/bin/isolated-functions.sh
+++ b/bin/isolated-functions.sh
@@@ -1,5 -1,5 +1,5 @@@
-#!/bin/bash
+#!@PORTAGE_BASH@
- # Copyright 1999-2014 Gentoo Foundation
+ # Copyright 1999-2016 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
source "${PORTAGE_BIN_PATH}/eapi.sh" || exit 1
diff --cc bin/misc-functions.sh
index a1d4088,15651b9..080e366
mode 100644,100755..100644
--- a/bin/misc-functions.sh
+++ b/bin/misc-functions.sh
diff --cc bin/portageq
index be35dc6,925640b..2e90cfa
--- a/bin/portageq
+++ b/bin/portageq
@@@ -1,5 -1,5 +1,5 @@@
-#!/usr/bin/python -bO
+#!@PREFIX_PORTAGE_PYTHON@ -bO
- # Copyright 1999-2014 Gentoo Foundation
+ # Copyright 1999-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
from __future__ import print_function, unicode_literals
diff --cc bin/repoman
index afc26c3,819e0f5..81b33f7
--- a/bin/repoman
+++ b/bin/repoman
@@@ -1,3152 -1,43 +1,43 @@@
-#!/usr/bin/python -bO
+#!@PREFIX_PORTAGE_PYTHON@ -bO
- # Copyright 1999-2015 Gentoo Foundation
+ # Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
- # Next to do: dep syntax checking in mask files
- # Then, check to make sure deps are satisfiable (to avoid "can't find match for" problems)
- # that last one is tricky because multiple profiles need to be checked.
+ """Ebuild and tree health checks and maintenance utilities.
+ """
- from __future__ import print_function, unicode_literals
+ from __future__ import print_function
- import codecs
- import copy
- import errno
- import io
- import logging
- import re
- import signal
- import stat
- import subprocess
import sys
- import tempfile
- import textwrap
- import time
- import platform
- from itertools import chain
- from stat import S_ISDIR
- from pprint import pformat
-
- try:
- from urllib.parse import urlparse
- except ImportError:
- from urlparse import urlparse
-
- from os import path as osp
- if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")):
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
- import portage
- portage._internal_caller = True
- portage._disable_legacy_globals()
-
+ import errno
+ # This block ensures that ^C interrupts are handled quietly.
try:
- import xml.etree.ElementTree
- from xml.parsers.expat import ExpatError
- except (SystemExit, KeyboardInterrupt):
- raise
- except (ImportError, SystemError, RuntimeError, Exception):
- # broken or missing xml support
- # http://bugs.python.org/issue14988
- msg = ["Please enable python's \"xml\" USE flag in order to use repoman."]
- from portage.output import EOutput
- out = EOutput()
- for line in msg:
- out.eerror(line)
- sys.exit(1)
-
- from portage import os
- from portage import _encodings
- from portage import _unicode_encode
- import portage.util.formatter as formatter
- import repoman.checks
- from repoman.checks import run_checks
- from repoman.check_missingslot import check_missingslot
- from repoman import utilities
- from repoman.herdbase import make_herd_base
- from _emerge.Package import Package
- from _emerge.RootConfig import RootConfig
- from _emerge.UserQuery import UserQuery
- import portage.checksum
- import portage.const
- import portage.repository.config
- from portage import cvstree, normalize_path
- from portage import util
- from portage.exception import (FileNotFound, InvalidAtom, MissingParameter,
- ParseError, PermissionDenied)
- from portage.dep import Atom
- from portage.process import find_binary, spawn
- from portage.output import bold, create_color_func, \
- green, nocolor, red
- from portage.output import ConsoleStyleFile, StyleWriter
- from portage.util import writemsg_level
- from portage.util._argparse import ArgumentParser
- from portage.package.ebuild.digestgen import digestgen
- from portage.eapi import eapi_has_iuse_defaults, eapi_has_required_use
-
- if sys.hexversion >= 0x3000000:
- basestring = str
+ import signal
- util.initialize_logger()
-
- # 14 is the length of DESCRIPTION=""
- max_desc_len = 100
- allowed_filename_chars="a-zA-Z0-9._+-"
- pv_toolong_re = re.compile(r'[0-9]{19,}')
- GPG_KEY_ID_REGEX = r'(0x)?([0-9a-fA-F]{8}|[0-9a-fA-F]{16}|[0-9a-fA-F]{24}|[0-9a-fA-F]{32}|[0-9a-fA-F]{40})!?'
- bad = create_color_func("BAD")
-
- # A sane umask is needed for files that portage creates.
- os.umask(0o22)
- # Repoman sets it's own ACCEPT_KEYWORDS and we don't want it to
- # behave incrementally.
- repoman_incrementals = tuple(x for x in \
- portage.const.INCREMENTALS if x != 'ACCEPT_KEYWORDS')
- config_root = os.environ.get("PORTAGE_CONFIGROOT")
- repoman_settings = portage.config(config_root=config_root, local_config=False)
-
- if repoman_settings.get("NOCOLOR", "").lower() in ("yes", "true") or \
- repoman_settings.get('TERM') == 'dumb' or \
- not sys.stdout.isatty():
- nocolor()
-
- def warn(txt):
- print("repoman: " + txt)
-
- def err(txt):
- warn(txt)
- sys.exit(1)
-
- def exithandler(signum=None, _frame=None):
- logging.fatal("Interrupted; exiting...")
- if signum is None:
- sys.exit(1)
- else:
+ def exithandler(signum, _frame):
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+ signal.signal(signal.SIGTERM, signal.SIG_IGN)
sys.exit(128 + signum)
- signal.signal(signal.SIGINT, exithandler)
-
- def ParseArgs(argv, qahelp):
- """This function uses a customized optionParser to parse command line arguments for repoman
- Args:
- argv - a sequence of command line arguments
- qahelp - a dict of qa warning to help message
- Returns:
- (opts, args), just like a call to parser.parse_args()
- """
-
- argv = portage._decode_argv(argv)
-
- modes = {
- 'commit' : 'Run a scan then commit changes',
- 'ci' : 'Run a scan then commit changes',
- 'fix' : 'Fix simple QA issues (stray digests, missing digests)',
- 'full' : 'Scan directory tree and print all issues (not a summary)',
- 'help' : 'Show this screen',
- 'manifest' : 'Generate a Manifest (fetches files if necessary)',
- 'manifest-check' : 'Check Manifests for missing or incorrect digests',
- 'scan' : 'Scan directory tree for QA issues'
- }
-
- output_choices = {
- 'default' : 'The normal output format',
- 'column' : 'Columnar output suitable for use with grep'
- }
-
- mode_keys = list(modes)
- mode_keys.sort()
-
- output_keys = sorted(output_choices)
-
- parser = ArgumentParser(usage="repoman [options] [mode]",
- description="Modes: %s" % " | ".join(mode_keys),
- epilog="For more help consult the man page.")
-
- parser.add_argument('-a', '--ask', dest='ask', action='store_true', default=False,
- help='Request a confirmation before commiting')
-
- parser.add_argument('-m', '--commitmsg', dest='commitmsg',
- help='specify a commit message on the command line')
-
- parser.add_argument('-M', '--commitmsgfile', dest='commitmsgfile',
- help='specify a path to a file that contains a commit message')
-
- parser.add_argument('--digest',
- choices=('y', 'n'), metavar='<y|n>',
- help='Automatically update Manifest digests for modified files')
-
- parser.add_argument('-p', '--pretend', dest='pretend', default=False,
- action='store_true', help='don\'t commit or fix anything; just show what would be done')
-
- parser.add_argument('-q', '--quiet', dest="quiet", action="count", default=0,
- help='do not print unnecessary messages')
-
- parser.add_argument(
- '--echangelog', choices=('y', 'n', 'force'), metavar="<y|n|force>",
- help='for commit mode, call echangelog if ChangeLog is unmodified (or '
- 'regardless of modification if \'force\' is specified)')
-
- parser.add_argument('--experimental-inherit', choices=('y', 'n'),
- metavar="<y|n>", default='n',
- help='Enable experimental inherit.missing checks which may misbehave'
- ' when the internal eclass database becomes outdated')
-
- parser.add_argument('-f', '--force', dest='force', default=False, action='store_true',
- help='Commit with QA violations')
-
- parser.add_argument('-S', '--straight-to-stable', dest='straight_to_stable', default=False,
- action='store_true', help='Allow committing straight to stable')
-
- parser.add_argument('--vcs', dest='vcs',
- help='Force using specific VCS instead of autodetection')
-
- parser.add_argument('-v', '--verbose', dest="verbosity", action='count',
- help='be very verbose in output', default=0)
-
- parser.add_argument('-V', '--version', dest='version', action='store_true',
- help='show version info')
-
- parser.add_argument('-x', '--xmlparse', dest='xml_parse', action='store_true',
- default=False, help='forces the metadata.xml parse check to be carried out')
-
- parser.add_argument(
- '--if-modified', choices=('y', 'n'), default='n',
- metavar="<y|n>",
- help='only check packages that have uncommitted modifications')
-
- parser.add_argument('-i', '--ignore-arches', dest='ignore_arches', action='store_true',
- default=False, help='ignore arch-specific failures (where arch != host)')
-
- parser.add_argument("--ignore-default-opts",
- action="store_true",
- help="do not use the REPOMAN_DEFAULT_OPTS environment variable")
-
- parser.add_argument('-I', '--ignore-masked', dest='ignore_masked', action='store_true',
- default=False, help='ignore masked packages (not allowed with commit mode)')
-
- parser.add_argument('--include-arches', dest='include_arches',
- metavar='ARCHES', action='append',
- help='A space separated list of arches used to '
- 'filter the selection of profiles for dependency checks')
-
- parser.add_argument('-d', '--include-dev', dest='include_dev', action='store_true',
- default=False, help='include dev profiles in dependency checks')
-
- parser.add_argument('-e', '--include-exp-profiles', choices=('y', 'n'),
- default=False, help='include exp profiles in dependency checks',
- metavar='<y|n>')
-
- parser.add_argument('--unmatched-removal', dest='unmatched_removal', action='store_true',
- default=False, help='enable strict checking of package.mask and package.unmask files for unmatched removal atoms')
-
- parser.add_argument('--without-mask', dest='without_mask', action='store_true',
- default=False, help='behave as if no package.mask entries exist (not allowed with commit mode)')
-
- parser.add_argument('--output-style', dest='output_style', choices=output_keys,
- help='select output type', default='default')
-
- parser.add_argument('--mode', dest='mode', choices=mode_keys,
- help='specify which mode repoman will run in (default=full)')
-
- opts, args = parser.parse_known_args(argv[1:])
-
- if not opts.ignore_default_opts:
- default_opts = portage.util.shlex_split(
- repoman_settings.get("REPOMAN_DEFAULT_OPTS", ""))
- if default_opts:
- opts, args = parser.parse_known_args(default_opts + sys.argv[1:])
-
- if opts.mode == 'help':
- parser.print_help(short=False)
-
- for arg in args:
- if arg in modes:
- if not opts.mode:
- opts.mode = arg
- break
- else:
- parser.error("invalid mode: %s" % arg)
-
- if not opts.mode:
- opts.mode = 'full'
-
- if opts.mode == 'ci':
- opts.mode = 'commit' # backwards compat shortcut
-
- # Use the verbosity and quiet options to fiddle with the loglevel appropriately
- for val in range(opts.verbosity):
- logger = logging.getLogger()
- logger.setLevel(logger.getEffectiveLevel() - 10)
-
- for val in range(opts.quiet):
- logger = logging.getLogger()
- logger.setLevel(logger.getEffectiveLevel() + 10)
-
- if opts.mode == 'commit' and not (opts.force or opts.pretend):
- if opts.ignore_masked:
- opts.ignore_masked = False
- logging.warning('Commit mode automatically disables --ignore-masked')
- if opts.without_mask:
- opts.without_mask = False
- logging.warning('Commit mode automatically disables --without-mask')
-
- return (opts, args)
-
- qahelp = {
- "CVS/Entries.IO_error": "Attempting to commit, and an IO error was encountered access the Entries file",
- "ebuild.invalidname": "Ebuild files with a non-parseable or syntactically incorrect name (or using 2.1 versioning extensions)",
- "ebuild.namenomatch": "Ebuild files that do not have the same name as their parent directory",
- "changelog.ebuildadded": "An ebuild was added but the ChangeLog was not modified",
- "changelog.missing": "Missing ChangeLog files",
- "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",
- "dependency.bad": "User-visible ebuilds with unsatisfied dependencies (matched against *visible* ebuilds)",
- "dependency.badmasked": "Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds)",
- "dependency.badindev": "User-visible ebuilds with unsatisfied dependencies (matched against *visible* ebuilds) in developing arch",
- "dependency.badmaskedindev": "Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds) in developing arch",
- "dependency.badtilde": "Uses the ~ dep operator with a non-zero revision part, which is useless (the revision is ignored)",
- "dependency.missingslot": "RDEPEND matches more than one SLOT but does not specify a slot and/or use the := or :* slot operator",
- "dependency.perlcore": "This ebuild directly depends on a package in perl-core; it should use the corresponding virtual instead.",
- "dependency.syntax": "Syntax error in dependency string (usually an extra/missing space/parenthesis)",
- "dependency.unknown": "Ebuild has a dependency that refers to an unknown package (which may be valid if it is a blocker for a renamed/removed package, or is an alternative choice provided by an overlay)",
- "file.executable": "Ebuilds, digests, metadata.xml, Manifest, and ChangeLog do not need the executable bit",
- "file.size": "Files in the files directory must be under 20 KiB",
- "file.size.fatal": "Files in the files directory must be under 60 KiB",
- "file.name": "File/dir name must be composed of only the following chars: %s " % allowed_filename_chars,
- "file.UTF8": "File is not UTF8 compliant",
- "inherit.deprecated": "Ebuild inherits a deprecated eclass",
- "inherit.missing": "Ebuild uses functions from an eclass but does not inherit it",
- "inherit.unused": "Ebuild inherits an eclass but does not use it",
- "java.eclassesnotused": "With virtual/jdk in DEPEND you must inherit a java eclass",
- "wxwidgets.eclassnotused": "Ebuild DEPENDs on x11-libs/wxGTK without inheriting wxwidgets.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",
- "KEYWORDS.stupid": "Ebuilds that use KEYWORDS=-* instead of package.mask",
- "LICENSE.missing": "Ebuilds that have a missing or empty LICENSE variable",
- "LICENSE.virtual": "Virtuals that have a non-empty LICENSE variable",
- "DESCRIPTION.missing": "Ebuilds that have a missing or empty DESCRIPTION variable",
- "DESCRIPTION.toolong": "DESCRIPTION is over %d characters" % max_desc_len,
- "EAPI.definition": "EAPI definition does not conform to PMS section 7.3.1 (first non-comment, non-blank line)",
- "EAPI.deprecated": "Ebuilds that use features that are deprecated in the current EAPI",
- "EAPI.incompatible": "Ebuilds that use features that are only available with a different EAPI",
- "EAPI.unsupported": "Ebuilds that have an unsupported EAPI version (you must upgrade portage)",
- "SLOT.invalid": "Ebuilds that have a missing or invalid SLOT variable value",
- "HOMEPAGE.missing": "Ebuilds that have a missing or empty HOMEPAGE variable",
- "HOMEPAGE.virtual": "Virtuals that have a non-empty HOMEPAGE variable",
- "PDEPEND.suspect": "PDEPEND contains a package that usually only belongs in DEPEND.",
- "LICENSE.syntax": "Syntax error in LICENSE (usually an extra/missing space/parenthesis)",
- "PROVIDE.syntax": "Syntax error in PROVIDE (usually an extra/missing space/parenthesis)",
- "PROPERTIES.syntax": "Syntax error in PROPERTIES (usually an extra/missing space/parenthesis)",
- "RESTRICT.syntax": "Syntax error in RESTRICT (usually an extra/missing space/parenthesis)",
- "REQUIRED_USE.syntax": "Syntax error in REQUIRED_USE (usually an extra/missing space/parenthesis)",
- "SRC_URI.syntax": "Syntax error in SRC_URI (usually an extra/missing space/parenthesis)",
- "SRC_URI.mirror": "A uri listed in profiles/thirdpartymirrors is found in SRC_URI",
- "ebuild.syntax": "Error generating cache entry for ebuild; typically caused by ebuild syntax error or digest verification failure",
- "ebuild.output": "A simple sourcing of the ebuild produces output; this breaks ebuild policy.",
- "ebuild.nesteddie": "Placing 'die' inside ( ) prints an error, but doesn't stop the ebuild.",
- "variable.invalidchar": "A variable contains an invalid character that is not part of the ASCII character set",
- "variable.readonly": "Assigning a readonly variable",
- "variable.usedwithhelpers": "Ebuild uses D, ROOT, ED, EROOT or EPREFIX with helpers",
- "LIVEVCS.stable": "This ebuild is a live checkout from a VCS but has stable keywords.",
- "LIVEVCS.unmasked": "This ebuild is a live checkout from a VCS but has keywords and is not masked in the global package.mask.",
- "IUSE.invalid": "This ebuild has a variable in IUSE that is not in the use.desc or its metadata.xml file",
- "IUSE.missing": "This ebuild has a USE conditional which references a flag that is not listed in IUSE",
- "IUSE.rubydeprecated": "The ebuild has set a ruby interpreter in USE_RUBY, that is not available as a ruby target anymore",
- "LICENSE.invalid": "This ebuild is listing a license that doesnt exist in portages license/ dir.",
- "LICENSE.deprecated": "This ebuild is listing a deprecated license.",
- "KEYWORDS.invalid": "This ebuild contains KEYWORDS that are not listed in profiles/arch.list or for which no valid profile was found",
- "RDEPEND.implicit": "RDEPEND is unset in the ebuild which triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4)",
- "RDEPEND.suspect": "RDEPEND contains a package that usually only belongs in DEPEND.",
- "RESTRICT.invalid": "This ebuild contains invalid RESTRICT values.",
- "digest.assumed": "Existing digest must be assumed correct (Package level only)",
- "digest.missing": "Some files listed in SRC_URI aren't referenced in the Manifest",
- "digest.unused": "Some files listed in the Manifest aren't referenced in SRC_URI",
- "ebuild.majorsyn": "This ebuild has a major syntax error that may cause the ebuild to fail partially or fully",
- "ebuild.minorsyn": "This ebuild has a minor syntax error that contravenes gentoo coding style",
- "ebuild.badheader": "This ebuild has a malformed header",
- "manifest.bad": "Manifest has missing or incorrect digests",
- "metadata.missing": "Missing metadata.xml files",
- "metadata.bad": "Bad metadata.xml files",
- "metadata.warning": "Warnings in metadata.xml files",
- "portage.internal": "The ebuild uses an internal Portage function or variable",
- "repo.eapi.banned": "The ebuild uses an EAPI which is banned by the repository's metadata/layout.conf settings",
- "repo.eapi.deprecated": "The ebuild uses an EAPI which is deprecated by the repository's metadata/layout.conf settings",
- "virtual.oldstyle": "The ebuild PROVIDEs an old-style virtual (see GLEP 37)",
- "virtual.suspect": "Ebuild contains a package that usually should be pulled via virtual/, not directly.",
- "usage.obsolete": "The ebuild makes use of an obsolete construct",
- "upstream.workaround": "The ebuild works around an upstream bug, an upstream bug should be filed and tracked in bugs.gentoo.org"
- }
-
- qacats = list(qahelp)
- qacats.sort()
-
- qawarnings = set((
- "changelog.ebuildadded",
- "changelog.missing",
- "changelog.notadded",
- "dependency.unknown",
- "digest.assumed",
- "digest.unused",
- "ebuild.notadded",
- "ebuild.nesteddie",
- "dependency.badmasked",
- "dependency.badindev",
- "dependency.badmaskedindev",
- "dependency.badtilde",
- "dependency.missingslot",
- "dependency.perlcore",
- "DESCRIPTION.toolong",
- "EAPI.deprecated",
- "HOMEPAGE.virtual",
- "LICENSE.deprecated",
- "LICENSE.virtual",
- "KEYWORDS.dropped",
- "KEYWORDS.stupid",
- "KEYWORDS.missing",
- "IUSE.invalid",
- "PDEPEND.suspect",
- "RDEPEND.implicit",
- "RDEPEND.suspect",
- "virtual.suspect",
- "RESTRICT.invalid",
- "ebuild.minorsyn",
- "ebuild.badheader",
- "ebuild.patches",
- "file.size",
- "inherit.unused",
- "inherit.deprecated",
- "java.eclassesnotused",
- "wxwidgets.eclassnotused",
- "metadata.warning",
- "portage.internal",
- "repo.eapi.deprecated",
- "usage.obsolete",
- "upstream.workaround",
- "LIVEVCS.stable",
- "LIVEVCS.unmasked",
- "IUSE.rubydeprecated",
- "SRC_URI.mirror",
- ))
-
- non_ascii_re = re.compile(r'[^\x00-\x7f]')
-
- missingvars = ["KEYWORDS", "LICENSE", "DESCRIPTION", "HOMEPAGE"]
- allvars = set(x for x in portage.auxdbkeys if not x.startswith("UNUSED_"))
- allvars.update(Package.metadata_keys)
- allvars = sorted(allvars)
- commitmessage = None
- for x in missingvars:
- x += ".missing"
- if x not in qacats:
- logging.warning('* missingvars values need to be added to qahelp ("%s")' % x)
- qacats.append(x)
- qawarnings.add(x)
-
- valid_restrict = frozenset(["binchecks", "bindist",
- "fetch", "installsources", "mirror", "preserve-libs",
- "primaryuri", "splitdebug", "strip", "test", "userpriv"])
-
- live_eclasses = portage.const.LIVE_ECLASSES
-
- suspect_rdepend = frozenset([
- "app-arch/cabextract",
- "app-arch/rpm2targz",
- "app-doc/doxygen",
- "dev-lang/nasm",
- "dev-lang/swig",
- "dev-lang/yasm",
- "dev-perl/extutils-pkgconfig",
- "dev-util/byacc",
- "dev-util/cmake",
- "dev-util/ftjam",
- "dev-util/gperf",
- "dev-util/gtk-doc",
- "dev-util/gtk-doc-am",
- "dev-util/intltool",
- "dev-util/jam",
- "dev-util/pkg-config-lite",
- "dev-util/pkgconf",
- "dev-util/pkgconfig",
- "dev-util/pkgconfig-openbsd",
- "dev-util/scons",
- "dev-util/unifdef",
- "dev-util/yacc",
- "media-gfx/ebdftopcf",
- "sys-apps/help2man",
- "sys-devel/autoconf",
- "sys-devel/automake",
- "sys-devel/bin86",
- "sys-devel/bison",
- "sys-devel/dev86",
- "sys-devel/flex",
- "sys-devel/m4",
- "sys-devel/pmake",
- "virtual/linux-sources",
- "virtual/pkgconfig",
- "x11-misc/bdftopcf",
- "x11-misc/imake",
- ])
-
- suspect_virtual = {
- "dev-util/pkg-config-lite":"virtual/pkgconfig",
- "dev-util/pkgconf":"virtual/pkgconfig",
- "dev-util/pkgconfig":"virtual/pkgconfig",
- "dev-util/pkgconfig-openbsd":"virtual/pkgconfig",
- "dev-libs/libusb":"virtual/libusb",
- "dev-libs/libusbx":"virtual/libusb",
- "dev-libs/libusb-compat":"virtual/libusb",
- }
-
- ruby_deprecated = frozenset([
- "ruby_targets_ree18",
- "ruby_targets_ruby18",
- ])
-
- metadata_xml_encoding = 'UTF-8'
- metadata_xml_declaration = '<?xml version="1.0" encoding="%s"?>' % \
- (metadata_xml_encoding,)
- metadata_doctype_name = 'pkgmetadata'
- metadata_dtd_uri = 'http://www.gentoo.org/dtd/metadata.dtd'
- # force refetch if the local copy creation time is older than this
- metadata_dtd_ctime_interval = 60 * 60 * 24 * 7 # 7 days
-
- # file.executable
- no_exec = frozenset(["Manifest", "ChangeLog", "metadata.xml"])
-
- options, arguments = ParseArgs(sys.argv, qahelp)
-
- if options.version:
- print("Portage", portage.VERSION)
- sys.exit(0)
-
- if options.experimental_inherit == 'y':
- # This is experimental, so it's non-fatal.
- qawarnings.add("inherit.missing")
- repoman.checks._init(experimental_inherit=True)
-
- # Set this to False when an extraordinary issue (generally
- # something other than a QA issue) makes it impossible to
- # commit (like if Manifest generation fails).
- can_force = True
-
- portdir, portdir_overlay, mydir = utilities.FindPortdir(repoman_settings)
- if portdir is None:
- sys.exit(1)
-
- myreporoot = os.path.basename(portdir_overlay)
- myreporoot += mydir[len(portdir_overlay):]
-
- if options.vcs:
- if options.vcs in ('cvs', 'svn', 'git', 'bzr', 'hg'):
- vcs = options.vcs
- else:
- vcs = None
- else:
- vcses = utilities.FindVCS()
- if len(vcses) > 1:
- print(red('*** Ambiguous workdir -- more than one VCS found at the same depth: %s.' % ', '.join(vcses)))
- print(red('*** Please either clean up your workdir or specify --vcs option.'))
- sys.exit(1)
- elif vcses:
- vcs = vcses[0]
- else:
- vcs = None
-
- if options.if_modified == "y" and vcs is None:
- logging.info("Not in a version controlled repository; "
- "disabling --if-modified.")
- options.if_modified = "n"
-
- # Disable copyright/mtime check if vcs does not preserve mtime (bug #324075).
- vcs_preserves_mtime = vcs in ('cvs', None)
-
- vcs_local_opts = repoman_settings.get("REPOMAN_VCS_LOCAL_OPTS", "").split()
- vcs_global_opts = repoman_settings.get("REPOMAN_VCS_GLOBAL_OPTS")
- if vcs_global_opts is None:
- if vcs in ('cvs', 'svn'):
- vcs_global_opts = "-q"
- else:
- vcs_global_opts = ""
- vcs_global_opts = vcs_global_opts.split()
-
- if options.mode == 'commit' and not options.pretend and not vcs:
- logging.info("Not in a version controlled repository; enabling pretend mode.")
- options.pretend = True
-
- # Ensure that current repository is in the list of enabled repositories.
- repodir = os.path.realpath(portdir_overlay)
- try:
- repoman_settings.repositories.get_repo_for_location(repodir)
- except KeyError:
- repo_name = portage.repository.config.RepoConfig._read_valid_repo_name(portdir_overlay)[0]
- layout_conf_data = portage.repository.config.parse_layout_conf(portdir_overlay)[0]
- if layout_conf_data['repo-name']:
- repo_name = layout_conf_data['repo-name']
- tmp_conf_file = io.StringIO(textwrap.dedent("""
- [%s]
- location = %s
- """) % (repo_name, portdir_overlay))
- # Ensure that the repository corresponding to $PWD overrides a
- # repository of the same name referenced by the existing PORTDIR
- # or PORTDIR_OVERLAY settings.
- repoman_settings['PORTDIR_OVERLAY'] = "%s %s" % \
- (repoman_settings.get('PORTDIR_OVERLAY', ''),
- portage._shell_quote(portdir_overlay))
- repositories = portage.repository.config.load_repository_config(repoman_settings, extra_files=[tmp_conf_file])
- # We have to call the config constructor again so that attributes
- # dependent on config.repositories are initialized correctly.
- repoman_settings = portage.config(config_root=config_root, local_config=False, repositories=repositories)
-
- root = repoman_settings['EROOT']
- trees = {
- root : {'porttree' : portage.portagetree(settings=repoman_settings)}
- }
- portdb = trees[root]['porttree'].dbapi
-
- # Constrain dependency resolution to the master(s)
- # that are specified in layout.conf.
- repo_config = repoman_settings.repositories.get_repo_for_location(repodir)
- portdb.porttrees = list(repo_config.eclass_db.porttrees)
- portdir = portdb.porttrees[0]
- commit_env = os.environ.copy()
- # list() is for iteration on a copy.
- for repo in list(repoman_settings.repositories):
- # all paths are canonical
- if repo.location not in repo_config.eclass_db.porttrees:
- del repoman_settings.repositories[repo.name]
-
- if repo_config.allow_provide_virtual:
- qawarnings.add("virtual.oldstyle")
-
- if repo_config.sign_commit:
- if vcs == 'git':
- # NOTE: It's possible to use --gpg-sign=key_id to specify the key in
- # the commit arguments. If key_id is unspecified, then it must be
- # configured by `git config user.signingkey key_id`.
- vcs_local_opts.append("--gpg-sign")
- if repoman_settings.get("PORTAGE_GPG_DIR"):
- # Pass GNUPGHOME to git for bug #462362.
- commit_env["GNUPGHOME"] = repoman_settings["PORTAGE_GPG_DIR"]
-
- # Pass GPG_TTY to git for bug #477728.
- try:
- commit_env["GPG_TTY"] = os.ttyname(sys.stdin.fileno())
- except OSError:
- pass
-
- # In order to disable manifest signatures, repos may set
- # "sign-manifests = false" in metadata/layout.conf. This
- # can be used to prevent merge conflicts like those that
- # thin-manifests is designed to prevent.
- sign_manifests = "sign" in repoman_settings.features and \
- repo_config.sign_manifest
+ signal.signal(signal.SIGINT, exithandler)
+ signal.signal(signal.SIGTERM, exithandler)
+ signal.signal(signal.SIGPIPE, signal.SIG_DFL)
- if repo_config.sign_manifest and repo_config.name == "gentoo" and \
- options.mode in ("commit",) and not sign_manifests:
- msg = ("The '%s' repository has manifest signatures enabled, "
- "but FEATURES=sign is currently disabled. In order to avoid this "
- "warning, enable FEATURES=sign in make.conf. Alternatively, "
- "repositories can disable manifest signatures by setting "
- "'sign-manifests = false' in metadata/layout.conf.") % \
- (repo_config.name,)
- for line in textwrap.wrap(msg, 60):
- logging.warning(line)
-
- if sign_manifests and options.mode in ("commit",) and \
- repoman_settings.get("PORTAGE_GPG_KEY") and \
- re.match(r'^%s$' % GPG_KEY_ID_REGEX,
- repoman_settings["PORTAGE_GPG_KEY"]) is None:
- logging.error("PORTAGE_GPG_KEY value is invalid: %s" %
- repoman_settings["PORTAGE_GPG_KEY"])
- sys.exit(1)
-
- manifest_hashes = repo_config.manifest_hashes
- if manifest_hashes is None:
- manifest_hashes = portage.const.MANIFEST2_HASH_DEFAULTS
-
- if options.mode in ("commit", "fix", "manifest"):
- if portage.const.MANIFEST2_REQUIRED_HASH not in manifest_hashes:
- msg = ("The 'manifest-hashes' setting in the '%s' repository's "
- "metadata/layout.conf does not contain the '%s' hash which "
- "is required by this portage version. You will have to "
- "upgrade portage if you want to generate valid manifests for "
- "this repository.") % \
- (repo_config.name, portage.const.MANIFEST2_REQUIRED_HASH)
- for line in textwrap.wrap(msg, 70):
- logging.error(line)
- sys.exit(1)
-
- unsupported_hashes = manifest_hashes.difference(
- portage.const.MANIFEST2_HASH_FUNCTIONS)
- if unsupported_hashes:
- msg = ("The 'manifest-hashes' setting in the '%s' repository's "
- "metadata/layout.conf contains one or more hash types '%s' "
- "which are not supported by this portage version. You will "
- "have to upgrade portage if you want to generate valid "
- "manifests for this repository.") % \
- (repo_config.name, " ".join(sorted(unsupported_hashes)))
- for line in textwrap.wrap(msg, 70):
- logging.error(line)
- sys.exit(1)
-
- if options.echangelog is None and repo_config.update_changelog:
- options.echangelog = 'y'
-
- if vcs is None:
- options.echangelog = 'n'
-
- # The --echangelog option causes automatic ChangeLog generation,
- # which invalidates changelog.ebuildadded and changelog.missing
- # checks.
- # Note: Some don't use ChangeLogs in distributed SCMs.
- # It will be generated on server side from scm log,
- # before package moves to the rsync server.
- # This is needed because they try to avoid merge collisions.
- # Gentoo's Council decided to always use the ChangeLog file.
- # TODO: shouldn't this just be switched on the repo, iso the VCS?
- check_changelog = options.echangelog not in ('y', 'force') and vcs in ('cvs', 'svn')
-
- if 'digest' in repoman_settings.features and options.digest != 'n':
- options.digest = 'y'
-
- logging.debug("vcs: %s" % (vcs,))
- logging.debug("repo config: %s" % (repo_config,))
- logging.debug("options: %s" % (options,))
-
- # It's confusing if these warnings are displayed without the user
- # being told which profile they come from, so disable them.
- env = os.environ.copy()
- env['FEATURES'] = env.get('FEATURES', '') + ' -unknown-features-warn'
-
- categories = []
- for path in repo_config.eclass_db.porttrees:
- categories.extend(portage.util.grabfile(
- os.path.join(path, 'profiles', 'categories')))
- repoman_settings.categories = frozenset(
- portage.util.stack_lists([categories], incremental=1))
- categories = repoman_settings.categories
-
- portdb.settings = repoman_settings
- root_config = RootConfig(repoman_settings, trees[root], None)
- # We really only need to cache the metadata that's necessary for visibility
- # filtering. Anything else can be discarded to reduce memory consumption.
- portdb._aux_cache_keys.clear()
- portdb._aux_cache_keys.update(["EAPI", "IUSE", "KEYWORDS", "repository", "SLOT"])
-
- reposplit = myreporoot.split(os.path.sep)
- repolevel = len(reposplit)
-
- # check if it's in $PORTDIR/$CATEGORY/$PN , otherwise bail if commiting.
- # Reason for this is if they're trying to commit in just $FILESDIR/*, the Manifest needs updating.
- # this check ensures that repoman knows where it is, and the manifest recommit is at least possible.
- if options.mode == 'commit' and repolevel not in [1, 2, 3]:
- print(red("***")+" Commit attempts *must* be from within a vcs co, category, or package directory.")
- print(red("***")+" Attempting to commit from a packages files directory will be blocked for instance.")
- print(red("***")+" This is intended behaviour, to ensure the manifest is recommitted for a package.")
- print(red("***"))
- err("Unable to identify level we're commiting from for %s" % '/'.join(reposplit))
-
- # Make startdir relative to the canonical repodir, so that we can pass
- # it to digestgen and it won't have to be canonicalized again.
- if repolevel == 1:
- startdir = repodir
- else:
- startdir = normalize_path(mydir)
- startdir = os.path.join(repodir, *startdir.split(os.sep)[-2 - repolevel + 3:])
-
- def caterror(mycat):
- err(mycat + " is not an official category. Skipping QA checks in this directory.\nPlease ensure that you add " + catdir + " to " + repodir + "/profiles/categories\nif it is a new category.")
-
- def repoman_getstatusoutput(cmd):
- """
- Implements an interface similar to getstatusoutput(), but with
- customized unicode handling (see bug #310789) and without the shell.
- """
- args = portage.util.shlex_split(cmd)
-
- if sys.hexversion < 0x3020000 and sys.hexversion >= 0x3000000 and \
- not os.path.isabs(args[0]):
- # Python 3.1 _execvp throws TypeError for non-absolute executable
- # path passed as bytes (see http://bugs.python.org/issue8513).
- fullname = find_binary(args[0])
- if fullname is None:
- raise portage.exception.CommandNotFound(args[0])
- args[0] = fullname
-
- encoding = _encodings['fs']
- args = [_unicode_encode(x,
- encoding=encoding, errors='strict') for x in args]
- proc = subprocess.Popen(args, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- output = portage._unicode_decode(proc.communicate()[0],
- encoding=encoding, errors='strict')
- if output and output[-1] == "\n":
- # getstatusoutput strips one newline
- output = output[:-1]
- return (proc.wait(), output)
-
- class repoman_popen(portage.proxy.objectproxy.ObjectProxy):
- """
- Implements an interface similar to os.popen(), but with customized
- unicode handling (see bug #310789) and without the shell.
- """
-
- __slots__ = ('_proc', '_stdout')
-
- def __init__(self, cmd):
- args = portage.util.shlex_split(cmd)
-
- if sys.hexversion < 0x3020000 and sys.hexversion >= 0x3000000 and \
- not os.path.isabs(args[0]):
- # Python 3.1 _execvp throws TypeError for non-absolute executable
- # path passed as bytes (see http://bugs.python.org/issue8513).
- fullname = find_binary(args[0])
- if fullname is None:
- raise portage.exception.CommandNotFound(args[0])
- args[0] = fullname
-
- encoding = _encodings['fs']
- args = [_unicode_encode(x,
- encoding=encoding, errors='strict') for x in args]
- proc = subprocess.Popen(args, stdout=subprocess.PIPE)
- object.__setattr__(self, '_proc', proc)
- object.__setattr__(self, '_stdout',
- codecs.getreader(encoding)(proc.stdout, 'strict'))
-
- def _get_target(self):
- return object.__getattribute__(self, '_stdout')
-
- __enter__ = _get_target
-
- def __exit__(self, exc_type, exc_value, traceback):
- proc = object.__getattribute__(self, '_proc')
- proc.wait()
- proc.stdout.close()
-
- class ProfileDesc(object):
- __slots__ = ('abs_path', 'arch', 'status', 'sub_path', 'tree_path',)
- def __init__(self, arch, status, sub_path, tree_path):
- self.arch = arch
- self.status = status
- if sub_path:
- sub_path = normalize_path(sub_path.lstrip(os.sep))
- self.sub_path = sub_path
- self.tree_path = tree_path
- if tree_path:
- self.abs_path = os.path.join(tree_path, 'profiles', self.sub_path)
- else:
- self.abs_path = tree_path
-
- def __str__(self):
- if self.sub_path:
- return self.sub_path
- return 'empty profile'
-
- profile_list = []
- valid_profile_types = frozenset(['dev', 'exp', 'stable'])
-
- # get lists of valid keywords, licenses, and use
- kwlist = set()
- liclist = set()
- uselist = set()
- global_pmasklines = []
-
- for path in portdb.porttrees:
- try:
- liclist.update(os.listdir(os.path.join(path, "licenses")))
- except OSError:
- pass
- kwlist.update(portage.grabfile(os.path.join(path,
- "profiles", "arch.list")))
-
- use_desc = portage.grabfile(os.path.join(path, 'profiles', 'use.desc'))
- for x in use_desc:
- x = x.split()
- if x:
- uselist.add(x[0])
-
- expand_desc_dir = os.path.join(path, 'profiles', 'desc')
- try:
- expand_list = os.listdir(expand_desc_dir)
- except OSError:
- pass
- else:
- for fn in expand_list:
- if not fn[-5:] == '.desc':
- continue
- use_prefix = fn[:-5].lower() + '_'
- for x in portage.grabfile(os.path.join(expand_desc_dir, fn)):
- x = x.split()
- if x:
- uselist.add(use_prefix + x[0])
-
- global_pmasklines.append(portage.util.grabfile_package(
- os.path.join(path, 'profiles', 'package.mask'), recursive=1, verify_eapi=True))
-
- desc_path = os.path.join(path, 'profiles', 'profiles.desc')
- try:
- desc_file = io.open(_unicode_encode(desc_path,
- encoding=_encodings['fs'], errors='strict'),
- mode='r', encoding=_encodings['repo.content'], errors='replace')
- except EnvironmentError:
- pass
- else:
- for i, x in enumerate(desc_file):
- if x[0] == "#":
- continue
- arch = x.split()
- if len(arch) == 0:
- continue
- if len(arch) != 3:
- err("wrong format: \"" + bad(x.strip()) + "\" in " + \
- desc_path + " line %d" % (i + 1, ))
- elif arch[0] not in kwlist:
- err("invalid arch: \"" + bad(arch[0]) + "\" in " + \
- desc_path + " line %d" % (i + 1, ))
- elif arch[2] not in valid_profile_types:
- err("invalid profile type: \"" + bad(arch[2]) + "\" in " + \
- desc_path + " line %d" % (i + 1, ))
- profile_desc = ProfileDesc(arch[0], arch[2], arch[1], path)
- if not os.path.isdir(profile_desc.abs_path):
- logging.error(
- "Invalid %s profile (%s) for arch %s in %s line %d",
- arch[2], arch[1], arch[0], desc_path, i + 1)
- continue
- if os.path.exists(
- os.path.join(profile_desc.abs_path, 'deprecated')):
- continue
- profile_list.append(profile_desc)
- desc_file.close()
-
- repoman_settings['PORTAGE_ARCHLIST'] = ' '.join(sorted(kwlist))
- repoman_settings.backup_changes('PORTAGE_ARCHLIST')
-
- global_pmasklines = portage.util.stack_lists(global_pmasklines, incremental=1)
- global_pmaskdict = {}
- for x in global_pmasklines:
- global_pmaskdict.setdefault(x.cp, []).append(x)
- del global_pmasklines
-
- def has_global_mask(pkg):
- mask_atoms = global_pmaskdict.get(pkg.cp)
- if mask_atoms:
- pkg_list = [pkg]
- for x in mask_atoms:
- if portage.dep.match_from_list(x, pkg_list):
- return x
- return None
-
- # Ensure that profile sub_path attributes are unique. Process in reverse order
- # so that profiles with duplicate sub_path from overlays will override
- # profiles with the same sub_path from parent repos.
- profiles = {}
- profile_list.reverse()
- profile_sub_paths = set()
- for prof in profile_list:
- if prof.sub_path in profile_sub_paths:
- continue
- profile_sub_paths.add(prof.sub_path)
- profiles.setdefault(prof.arch, []).append(prof)
-
- # Use an empty profile for checking dependencies of
- # packages that have empty KEYWORDS.
- prof = ProfileDesc('**', 'stable', '', '')
- profiles.setdefault(prof.arch, []).append(prof)
-
- for x in repoman_settings.archlist():
- if x[0] == "~":
- continue
- if x not in profiles:
- print(red("\"" + x + "\" doesn't have a valid profile listed in profiles.desc."))
- print(red("You need to either \"cvs update\" your profiles dir or follow this"))
- print(red("up with the " + x + " team."))
- print()
-
- liclist_deprecated = set()
- if "DEPRECATED" in repoman_settings._license_manager._license_groups:
- liclist_deprecated.update(
- repoman_settings._license_manager.expandLicenseTokens(["@DEPRECATED"]))
-
- if not liclist:
- logging.fatal("Couldn't find licenses?")
- sys.exit(1)
-
- if not kwlist:
- logging.fatal("Couldn't read KEYWORDS from arch.list")
- sys.exit(1)
-
- if not uselist:
- logging.fatal("Couldn't find use.desc?")
+ except KeyboardInterrupt:
sys.exit(1)
- scanlist = []
- if repolevel == 2:
- # we are inside a category directory
- catdir = reposplit[-1]
- if catdir not in categories:
- caterror(catdir)
- mydirlist = os.listdir(startdir)
- for x in mydirlist:
- if x == "CVS" or x.startswith("."):
- continue
- if os.path.isdir(startdir + "/" + x):
- scanlist.append(catdir + "/" + x)
- repo_subdir = catdir + os.sep
- elif repolevel == 1:
- for x in categories:
- if not os.path.isdir(startdir + "/" + x):
- continue
- for y in os.listdir(startdir + "/" + x):
- if y == "CVS" or y.startswith("."):
- continue
- if os.path.isdir(startdir + "/" + x + "/" + y):
- scanlist.append(x + "/" + y)
- repo_subdir = ""
- elif repolevel == 3:
- catdir = reposplit[-2]
- if catdir not in categories:
- caterror(catdir)
- scanlist.append(catdir + "/" + reposplit[-1])
- repo_subdir = scanlist[-1] + os.sep
- else:
- msg = 'Repoman is unable to determine PORTDIR or PORTDIR_OVERLAY' + \
- ' from the current working directory'
- logging.critical(msg)
- sys.exit(1)
-
- repo_subdir_len = len(repo_subdir)
- scanlist.sort()
-
- logging.debug("Found the following packages to scan:\n%s" % '\n'.join(scanlist))
-
- def vcs_files_to_cps(vcs_file_iter):
- """
- Iterate over the given modified file paths returned from the vcs,
- and return a frozenset containing category/pn strings for each
- modified package.
- """
-
- modified_cps = []
-
- if repolevel == 3:
- if reposplit[-2] in categories and \
- next(vcs_file_iter, None) is not None:
- modified_cps.append("/".join(reposplit[-2:]))
-
- elif repolevel == 2:
- category = reposplit[-1]
- if category in categories:
- for filename in vcs_file_iter:
- f_split = filename.split(os.sep)
- # ['.', pn, ...]
- if len(f_split) > 2:
- modified_cps.append(category + "/" + f_split[1])
-
- else:
- # repolevel == 1
- for filename in vcs_file_iter:
- f_split = filename.split(os.sep)
- # ['.', category, pn, ...]
- if len(f_split) > 3 and f_split[1] in categories:
- modified_cps.append("/".join(f_split[1:3]))
-
- # Exclude packages that have been removed, since calling
- # code assumes that the packages exist.
- return frozenset(x for x in frozenset(modified_cps)
- if os.path.exists(os.path.join(repodir, x)))
-
- def git_supports_gpg_sign():
- status, cmd_output = \
- repoman_getstatusoutput("git --version")
- cmd_output = cmd_output.split()
- if cmd_output:
- version = re.match(r'^(\d+)\.(\d+)\.(\d+)', cmd_output[-1])
- if version is not None:
- version = [int(x) for x in version.groups()]
- if version[0] > 1 or \
- (version[0] == 1 and version[1] > 7) or \
- (version[0] == 1 and version[1] == 7 and version[2] >= 9):
- return True
- return False
-
- def dev_keywords(profiles):
- """
- Create a set of KEYWORDS values that exist in 'dev'
- profiles. These are used
- to trigger a message notifying the user when they might
- want to add the --include-dev option.
- """
- type_arch_map = {}
- for arch, arch_profiles in profiles.items():
- for prof in arch_profiles:
- arch_set = type_arch_map.get(prof.status)
- if arch_set is None:
- arch_set = set()
- type_arch_map[prof.status] = arch_set
- arch_set.add(arch)
-
- dev_keywords = type_arch_map.get('dev', set())
- dev_keywords.update(['~' + arch for arch in dev_keywords])
- return frozenset(dev_keywords)
-
- dev_keywords = dev_keywords(profiles)
-
- stats = {}
- fails = {}
-
- for x in qacats:
- stats[x] = 0
- fails[x] = []
-
- xmllint_capable = False
- metadata_dtd = os.path.join(repoman_settings["DISTDIR"], 'metadata.dtd')
-
- def fetch_metadata_dtd():
- """
- Fetch metadata.dtd if it doesn't exist or the ctime is older than
- metadata_dtd_ctime_interval.
- @rtype: bool
- @return: True if successful, otherwise False
- """
-
- must_fetch = True
- metadata_dtd_st = None
- current_time = int(time.time())
- try:
- metadata_dtd_st = os.stat(metadata_dtd)
- except EnvironmentError as e:
- if e.errno not in (errno.ENOENT, errno.ESTALE):
- raise
- del e
- else:
- # Trigger fetch if metadata.dtd mtime is old or clock is wrong.
- if abs(current_time - metadata_dtd_st.st_ctime) \
- < metadata_dtd_ctime_interval:
- must_fetch = False
-
- if must_fetch:
- print()
- print(green("***") + " the local copy of metadata.dtd " + \
- "needs to be refetched, doing that now")
- print()
- parsed_url = urlparse(metadata_dtd_uri)
- setting = 'FETCHCOMMAND_' + parsed_url.scheme.upper()
- fcmd = repoman_settings.get(setting)
- if not fcmd:
- fcmd = repoman_settings.get('FETCHCOMMAND')
- if not fcmd:
- logging.error("FETCHCOMMAND is unset")
- return False
-
- destdir = repoman_settings["DISTDIR"]
- fd, metadata_dtd_tmp = tempfile.mkstemp(
- prefix='metadata.dtd.', dir=destdir)
- os.close(fd)
-
- try:
- if not portage.getbinpkg.file_get(metadata_dtd_uri,
- destdir, fcmd=fcmd,
- filename=os.path.basename(metadata_dtd_tmp)):
- logging.error("failed to fetch metadata.dtd from '%s'" %
- metadata_dtd_uri)
- return False
-
- try:
- portage.util.apply_secpass_permissions(metadata_dtd_tmp,
- gid=portage.data.portage_gid, mode=0o664, mask=0o2)
- except portage.exception.PortageException:
- pass
-
- os.rename(metadata_dtd_tmp, metadata_dtd)
- finally:
- try:
- os.unlink(metadata_dtd_tmp)
- except OSError:
- pass
-
- return True
-
- if options.mode == "manifest":
- pass
- elif not find_binary('xmllint'):
- print(red("!!! xmllint not found. Can't check metadata.xml.\n"))
- if options.xml_parse or repolevel == 3:
- print(red("!!!")+" sorry, xmllint is needed. failing\n")
- sys.exit(1)
- else:
- if not fetch_metadata_dtd():
- sys.exit(1)
- # this can be problematic if xmllint changes their output
- xmllint_capable = True
-
- if options.mode == 'commit' and vcs:
- utilities.detect_vcs_conflicts(options, vcs)
-
- if options.mode == "manifest":
- pass
- elif options.pretend:
- print(green("\nRepoMan does a once-over of the neighborhood..."))
- else:
- print(green("\nRepoMan scours the neighborhood..."))
-
- new_ebuilds = set()
- modified_ebuilds = set()
- modified_changelogs = set()
- mychanged = []
- mynew = []
- myremoved = []
-
- if (options.if_modified != "y" and
- options.mode in ("manifest", "manifest-check")):
- pass
- elif vcs == "cvs":
- mycvstree = cvstree.getentries("./", recursive=1)
- mychanged = cvstree.findchanged(mycvstree, recursive=1, basedir="./")
- mynew = cvstree.findnew(mycvstree, recursive=1, basedir="./")
- if options.if_modified == "y":
- myremoved = cvstree.findremoved(mycvstree, recursive=1, basedir="./")
-
- elif vcs == "svn":
- with repoman_popen("svn status") as f:
- svnstatus = f.readlines()
- mychanged = ["./" + elem.split()[-1:][0] for elem in svnstatus if elem and elem[:1] in "MR"]
- mynew = ["./" + elem.split()[-1:][0] for elem in svnstatus if elem.startswith("A")]
- if options.if_modified == "y":
- myremoved = ["./" + elem.split()[-1:][0] for elem in svnstatus if elem.startswith("D")]
-
- elif vcs == "git":
- with repoman_popen("git diff-index --name-only "
- "--relative --diff-filter=M HEAD") as f:
- mychanged = f.readlines()
- mychanged = ["./" + elem[:-1] for elem in mychanged]
-
- with repoman_popen("git diff-index --name-only "
- "--relative --diff-filter=A HEAD") as f:
- mynew = f.readlines()
- mynew = ["./" + elem[:-1] for elem in mynew]
- if options.if_modified == "y":
- with repoman_popen("git diff-index --name-only "
- "--relative --diff-filter=D HEAD") as f:
- myremoved = f.readlines()
- myremoved = ["./" + elem[:-1] for elem in myremoved]
-
- elif vcs == "bzr":
- with repoman_popen("bzr status -S .") as f:
- bzrstatus = f.readlines()
- mychanged = ["./" + elem.split()[-1:][0].split('/')[-1:][0] for elem in bzrstatus if elem and elem[1:2] == "M"]
- mynew = ["./" + elem.split()[-1:][0].split('/')[-1:][0] for elem in bzrstatus if elem and (elem[1:2] == "NK" or elem[0:1] == "R")]
- if options.if_modified == "y":
- myremoved = ["./" + elem.split()[-3:-2][0].split('/')[-1:][0] for elem in bzrstatus if elem and (elem[1:2] == "K" or elem[0:1] == "R")]
-
- elif vcs == "hg":
- with repoman_popen("hg status --no-status --modified .") as f:
- mychanged = f.readlines()
- mychanged = ["./" + elem.rstrip() for elem in mychanged]
- with repoman_popen("hg status --no-status --added .") as f:
- mynew = f.readlines()
- mynew = ["./" + elem.rstrip() for elem in mynew]
- if options.if_modified == "y":
- with repoman_popen("hg status --no-status --removed .") as f:
- myremoved = f.readlines()
- myremoved = ["./" + elem.rstrip() for elem in myremoved]
-
- if vcs:
- new_ebuilds.update(x for x in mynew if x.endswith(".ebuild"))
- modified_ebuilds.update(x for x in mychanged if x.endswith(".ebuild"))
- modified_changelogs.update(x for x in chain(mychanged, mynew) \
- if os.path.basename(x) == "ChangeLog")
-
- def vcs_new_changed(relative_path):
- for x in chain(mychanged, mynew):
- if x == relative_path:
- return True
- return False
-
- have_pmasked = False
- have_dev_keywords = False
- dofail = 0
-
- # NOTE: match-all caches are not shared due to potential
- # differences between profiles in _get_implicit_iuse.
- arch_caches = {}
- arch_xmatch_caches = {}
- shared_xmatch_caches = {"cp-list":{}}
-
- include_arches = None
- if options.include_arches:
- include_arches = set()
- include_arches.update(*[x.split() for x in options.include_arches])
-
- # Disable the "ebuild.notadded" check when not in commit mode and
- # running `svn status` in every package dir will be too expensive.
-
- check_ebuild_notadded = not \
- (vcs == "svn" and repolevel < 3 and options.mode != "commit")
-
- # Build a regex from thirdpartymirrors for the SRC_URI.mirror check.
- thirdpartymirrors = {}
- for k, v in repoman_settings.thirdpartymirrors().items():
- for v in v:
- if not v.endswith("/"):
- v += "/"
- thirdpartymirrors[v] = k
-
- class _XMLParser(xml.etree.ElementTree.XMLParser):
-
- def __init__(self, data, **kwargs):
- xml.etree.ElementTree.XMLParser.__init__(self, **kwargs)
- self._portage_data = data
- if hasattr(self, 'parser'):
- self._base_XmlDeclHandler = self.parser.XmlDeclHandler
- self.parser.XmlDeclHandler = self._portage_XmlDeclHandler
- self._base_StartDoctypeDeclHandler = \
- self.parser.StartDoctypeDeclHandler
- self.parser.StartDoctypeDeclHandler = \
- self._portage_StartDoctypeDeclHandler
-
- def _portage_XmlDeclHandler(self, version, encoding, standalone):
- if self._base_XmlDeclHandler is not None:
- self._base_XmlDeclHandler(version, encoding, standalone)
- self._portage_data["XML_DECLARATION"] = (version, encoding, standalone)
-
- def _portage_StartDoctypeDeclHandler(self, doctypeName, systemId, publicId,
- has_internal_subset):
- if self._base_StartDoctypeDeclHandler is not None:
- self._base_StartDoctypeDeclHandler(doctypeName, systemId, publicId,
- has_internal_subset)
- self._portage_data["DOCTYPE"] = (doctypeName, systemId, publicId)
-
- class _MetadataTreeBuilder(xml.etree.ElementTree.TreeBuilder):
- """
- Implements doctype() as required to avoid deprecation warnings with
- >=python-2.7.
- """
- def doctype(self, name, pubid, system):
- pass
+ from os import path as osp
+ if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")):
+ pym_path = osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym")
+ sys.path.insert(0, pym_path)
+ import portage
+ portage._internal_caller = True
+ from repoman.main import repoman_main
try:
- herd_base = make_herd_base(os.path.join(repoman_settings["PORTDIR"], "metadata/herds.xml"))
- except (EnvironmentError, ParseError, PermissionDenied) as e:
- err(str(e))
- except FileNotFound:
- # TODO: Download as we do for metadata.dtd, but add a way to
- # disable for non-gentoo repoman users who may not have herds.
- herd_base = None
-
- effective_scanlist = scanlist
- if options.if_modified == "y":
- effective_scanlist = sorted(vcs_files_to_cps(
- chain(mychanged, mynew, myremoved)))
-
- for x in effective_scanlist:
- # ebuilds and digests added to cvs respectively.
- logging.info("checking package %s" % x)
- # save memory by discarding xmatch caches from previous package(s)
- arch_xmatch_caches.clear()
- eadded = []
- catdir, pkgdir = x.split("/")
- checkdir = repodir + "/" + x
- checkdir_relative = ""
- if repolevel < 3:
- checkdir_relative = os.path.join(pkgdir, checkdir_relative)
- if repolevel < 2:
- checkdir_relative = os.path.join(catdir, checkdir_relative)
- checkdir_relative = os.path.join(".", checkdir_relative)
- generated_manifest = False
-
- if options.mode == "manifest" or \
- (options.mode != 'manifest-check' and options.digest == 'y') or \
- options.mode in ('commit', 'fix') and not options.pretend:
- auto_assumed = set()
- fetchlist_dict = portage.FetchlistDict(checkdir,
- repoman_settings, portdb)
- if options.mode == 'manifest' and options.force:
- portage._doebuild_manifest_exempt_depend += 1
- try:
- distdir = repoman_settings['DISTDIR']
- mf = repoman_settings.repositories.get_repo_for_location(
- os.path.dirname(os.path.dirname(checkdir)))
- mf = mf.load_manifest(checkdir, distdir,
- fetchlist_dict=fetchlist_dict)
- mf.create(requiredDistfiles=None,
- assumeDistHashesAlways=True)
- for distfiles in fetchlist_dict.values():
- for distfile in distfiles:
- if os.path.isfile(os.path.join(distdir, distfile)):
- mf.fhashdict['DIST'].pop(distfile, None)
- else:
- auto_assumed.add(distfile)
- mf.write()
- finally:
- portage._doebuild_manifest_exempt_depend -= 1
-
- repoman_settings["O"] = checkdir
- try:
- generated_manifest = digestgen(
- mysettings=repoman_settings, myportdb=portdb)
- except portage.exception.PermissionDenied as e:
- generated_manifest = False
- writemsg_level("!!! Permission denied: '%s'\n" % (e,),
- level=logging.ERROR, noiselevel=-1)
-
- if not generated_manifest:
- print("Unable to generate manifest.")
- dofail = 1
-
- if options.mode == "manifest":
- if not dofail and options.force and auto_assumed and \
- 'assume-digests' in repoman_settings.features:
- # Show which digests were assumed despite the --force option
- # being given. This output will already have been shown by
- # digestgen() if assume-digests is not enabled, so only show
- # it here if assume-digests is enabled.
- pkgs = list(fetchlist_dict)
- pkgs.sort()
- portage.writemsg_stdout(" digest.assumed" + \
- portage.output.colorize("WARN",
- str(len(auto_assumed)).rjust(18)) + "\n")
- for cpv in pkgs:
- fetchmap = fetchlist_dict[cpv]
- pf = portage.catsplit(cpv)[1]
- for distfile in sorted(fetchmap):
- if distfile in auto_assumed:
- portage.writemsg_stdout(
- " %s::%s\n" % (pf, distfile))
- continue
- elif dofail:
- sys.exit(1)
-
- if not generated_manifest:
- repoman_settings['O'] = checkdir
- repoman_settings['PORTAGE_QUIET'] = '1'
- if not portage.digestcheck([], repoman_settings, strict=1):
- stats["manifest.bad"] += 1
- fails["manifest.bad"].append(os.path.join(x, 'Manifest'))
- repoman_settings.pop('PORTAGE_QUIET', None)
-
- if options.mode == 'manifest-check':
- continue
-
- checkdirlist = os.listdir(checkdir)
- ebuildlist = []
- pkgs = {}
- allvalid = True
- for y in checkdirlist:
- if (y in no_exec or y.endswith(".ebuild")) and \
- stat.S_IMODE(os.stat(os.path.join(checkdir, y)).st_mode) & 0o111:
- stats["file.executable"] += 1
- fails["file.executable"].append(os.path.join(checkdir, y))
- if y.endswith(".ebuild"):
- pf = y[:-7]
- ebuildlist.append(pf)
- cpv = "%s/%s" % (catdir, pf)
- try:
- myaux = dict(zip(allvars, portdb.aux_get(cpv, allvars)))
- except KeyError:
- allvalid = False
- stats["ebuild.syntax"] += 1
- fails["ebuild.syntax"].append(os.path.join(x, y))
- continue
- except IOError:
- allvalid = False
- stats["ebuild.output"] += 1
- fails["ebuild.output"].append(os.path.join(x, y))
- continue
- if not portage.eapi_is_supported(myaux["EAPI"]):
- allvalid = False
- stats["EAPI.unsupported"] += 1
- fails["EAPI.unsupported"].append(os.path.join(x, y))
- continue
- pkgs[pf] = Package(cpv=cpv, metadata=myaux,
- root_config=root_config, type_name="ebuild")
-
- slot_keywords = {}
-
- if len(pkgs) != len(ebuildlist):
- # If we can't access all the metadata then it's totally unsafe to
- # commit since there's no way to generate a correct Manifest.
- # Do not try to do any more QA checks on this package since missing
- # metadata leads to false positives for several checks, and false
- # positives confuse users.
- can_force = False
- continue
-
- # Sort ebuilds in ascending order for the KEYWORDS.dropped check.
- ebuildlist = sorted(pkgs.values())
- ebuildlist = [pkg.pf for pkg in ebuildlist]
-
- for y in checkdirlist:
- index = repo_config.find_invalid_path_char(y)
- if index != -1:
- y_relative = os.path.join(checkdir_relative, y)
- if vcs is not None and not vcs_new_changed(y_relative):
- # If the file isn't in the VCS new or changed set, then
- # assume that it's an irrelevant temporary file (Manifest
- # entries are not generated for file names containing
- # prohibited characters). See bug #406877.
- index = -1
- if index != -1:
- stats["file.name"] += 1
- fails["file.name"].append("%s/%s: char '%s'" % \
- (checkdir, y, y[index]))
-
- if not (y in ("ChangeLog", "metadata.xml") or y.endswith(".ebuild")):
- continue
- f = None
- try:
- line = 1
- f = io.open(_unicode_encode(os.path.join(checkdir, y),
- encoding=_encodings['fs'], errors='strict'),
- mode='r', encoding=_encodings['repo.content'])
- for l in f:
- line += 1
- except UnicodeDecodeError as ue:
- stats["file.UTF8"] += 1
- s = ue.object[:ue.start]
- l2 = s.count("\n")
- line += l2
- if l2 != 0:
- s = s[s.rfind("\n") + 1:]
- fails["file.UTF8"].append("%s/%s: line %i, just after: '%s'" % (checkdir, y, line, s))
- finally:
- if f is not None:
- f.close()
-
- if vcs in ("git", "hg") and check_ebuild_notadded:
- if vcs == "git":
- myf = repoman_popen("git ls-files --others %s" % \
- (portage._shell_quote(checkdir_relative),))
- if vcs == "hg":
- myf = repoman_popen("hg status --no-status --unknown %s" % \
- (portage._shell_quote(checkdir_relative),))
- for l in myf:
- if l[:-1][-7:] == ".ebuild":
- stats["ebuild.notadded"] += 1
- fails["ebuild.notadded"].append(
- os.path.join(x, os.path.basename(l[:-1])))
- myf.close()
-
- if vcs in ("cvs", "svn", "bzr") and check_ebuild_notadded:
- try:
- if vcs == "cvs":
- myf = open(checkdir + "/CVS/Entries", "r")
- if vcs == "svn":
- myf = repoman_popen("svn status --depth=files --verbose " +
- portage._shell_quote(checkdir))
- if vcs == "bzr":
- myf = repoman_popen("bzr ls -v --kind=file " +
- portage._shell_quote(checkdir))
- myl = myf.readlines()
- myf.close()
- for l in myl:
- if vcs == "cvs":
- if l[0] != "/":
- continue
- splitl = l[1:].split("/")
- if not len(splitl):
- continue
- if splitl[0][-7:] == ".ebuild":
- eadded.append(splitl[0][:-7])
- if vcs == "svn":
- if l[:1] == "?":
- continue
- if l[:7] == ' >':
- # tree conflict, new in subversion 1.6
- continue
- l = l.split()[-1]
- if l[-7:] == ".ebuild":
- eadded.append(os.path.basename(l[:-7]))
- if vcs == "bzr":
- if l[1:2] == "?":
- continue
- l = l.split()[-1]
- if l[-7:] == ".ebuild":
- eadded.append(os.path.basename(l[:-7]))
- if vcs == "svn":
- myf = repoman_popen("svn status " +
- portage._shell_quote(checkdir))
- myl = myf.readlines()
- myf.close()
- for l in myl:
- if l[0] == "A":
- l = l.rstrip().split(' ')[-1]
- if l[-7:] == ".ebuild":
- eadded.append(os.path.basename(l[:-7]))
- except IOError:
- if vcs == "cvs":
- stats["CVS/Entries.IO_error"] += 1
- fails["CVS/Entries.IO_error"].append(checkdir + "/CVS/Entries")
- else:
- raise
- continue
-
- mf = repoman_settings.repositories.get_repo_for_location(
- os.path.dirname(os.path.dirname(checkdir)))
- mf = mf.load_manifest(checkdir, repoman_settings["DISTDIR"])
- mydigests = mf.getTypeDigests("DIST")
-
- fetchlist_dict = portage.FetchlistDict(checkdir, repoman_settings, portdb)
- myfiles_all = []
- src_uri_error = False
- for mykey in fetchlist_dict:
- try:
- myfiles_all.extend(fetchlist_dict[mykey])
- except portage.exception.InvalidDependString as e:
- src_uri_error = True
- try:
- portdb.aux_get(mykey, ["SRC_URI"])
- except KeyError:
- # This will be reported as an "ebuild.syntax" error.
- pass
- else:
- stats["SRC_URI.syntax"] += 1
- fails["SRC_URI.syntax"].append(
- "%s.ebuild SRC_URI: %s" % (mykey, e))
- del fetchlist_dict
- if not src_uri_error:
- # This test can produce false positives if SRC_URI could not
- # be parsed for one or more ebuilds. There's no point in
- # producing a false error here since the root cause will
- # produce a valid error elsewhere, such as "SRC_URI.syntax"
- # or "ebuild.sytax".
- myfiles_all = set(myfiles_all)
- for entry in mydigests:
- if entry not in myfiles_all:
- stats["digest.unused"] += 1
- fails["digest.unused"].append(checkdir + "::" + entry)
- for entry in myfiles_all:
- if entry not in mydigests:
- stats["digest.missing"] += 1
- fails["digest.missing"].append(checkdir + "::" + entry)
- del myfiles_all
-
- if os.path.exists(checkdir + "/files"):
- filesdirlist = os.listdir(checkdir + "/files")
-
- # recurse through files directory
- # use filesdirlist as a stack, appending directories as needed so people can't hide > 20k files in a subdirectory.
- while filesdirlist:
- y = filesdirlist.pop(0)
- relative_path = os.path.join(x, "files", y)
- full_path = os.path.join(repodir, relative_path)
- try:
- mystat = os.stat(full_path)
- except OSError as oe:
- if oe.errno == 2:
- # don't worry about it. it likely was removed via fix above.
- continue
- else:
- raise oe
- if S_ISDIR(mystat.st_mode):
- # !!! VCS "portability" alert! Need some function isVcsDir() or alike !!!
- if y == "CVS" or y == ".svn":
- continue
- for z in os.listdir(checkdir + "/files/" + y):
- if z == "CVS" or z == ".svn":
- continue
- filesdirlist.append(y + "/" + z)
- # Current policy is no files over 20 KiB, these are the checks. File size between
- # 20 KiB and 60 KiB causes a warning, while file size over 60 KiB causes an error.
- elif mystat.st_size > 61440:
- stats["file.size.fatal"] += 1
- fails["file.size.fatal"].append("(" + str(mystat.st_size//1024) + " KiB) " + x + "/files/" + y)
- elif mystat.st_size > 20480:
- stats["file.size"] += 1
- fails["file.size"].append("(" + str(mystat.st_size//1024) + " KiB) " + x + "/files/" + y)
-
- index = repo_config.find_invalid_path_char(y)
- if index != -1:
- y_relative = os.path.join(checkdir_relative, "files", y)
- if vcs is not None and not vcs_new_changed(y_relative):
- # If the file isn't in the VCS new or changed set, then
- # assume that it's an irrelevant temporary file (Manifest
- # entries are not generated for file names containing
- # prohibited characters). See bug #406877.
- index = -1
- if index != -1:
- stats["file.name"] += 1
- fails["file.name"].append("%s/files/%s: char '%s'" % \
- (checkdir, y, y[index]))
- del mydigests
-
- if check_changelog and "ChangeLog" not in checkdirlist:
- stats["changelog.missing"] += 1
- fails["changelog.missing"].append(x + "/ChangeLog")
-
- musedict = {}
- # metadata.xml file check
- if "metadata.xml" not in checkdirlist:
- stats["metadata.missing"] += 1
- fails["metadata.missing"].append(x + "/metadata.xml")
- # metadata.xml parse check
- else:
- metadata_bad = False
- xml_info = {}
- xml_parser = _XMLParser(xml_info, target=_MetadataTreeBuilder())
-
- # read metadata.xml into memory
- try:
- _metadata_xml = xml.etree.ElementTree.parse(
- _unicode_encode(os.path.join(checkdir, "metadata.xml"),
- encoding=_encodings['fs'], errors='strict'),
- parser=xml_parser)
- except (ExpatError, SyntaxError, EnvironmentError) as e:
- metadata_bad = True
- stats["metadata.bad"] += 1
- fails["metadata.bad"].append("%s/metadata.xml: %s" % (x, e))
- del e
- else:
- if not hasattr(xml_parser, 'parser') or \
- sys.hexversion < 0x2070000 or \
- (sys.hexversion > 0x3000000 and sys.hexversion < 0x3020000):
- # doctype is not parsed with python 2.6 or 3.1
- pass
- else:
- if "XML_DECLARATION" not in xml_info:
- stats["metadata.bad"] += 1
- fails["metadata.bad"].append("%s/metadata.xml: "
- "xml declaration is missing on first line, "
- "should be '%s'" % (x, metadata_xml_declaration))
- else:
- xml_version, xml_encoding, xml_standalone = \
- xml_info["XML_DECLARATION"]
- if xml_encoding is None or \
- xml_encoding.upper() != metadata_xml_encoding:
- stats["metadata.bad"] += 1
- if xml_encoding is None:
- encoding_problem = "but it is undefined"
- else:
- encoding_problem = "not '%s'" % xml_encoding
- fails["metadata.bad"].append("%s/metadata.xml: "
- "xml declaration encoding should be '%s', %s" %
- (x, metadata_xml_encoding, encoding_problem))
-
- if "DOCTYPE" not in xml_info:
- metadata_bad = True
- stats["metadata.bad"] += 1
- fails["metadata.bad"].append("%s/metadata.xml: %s" % (x,
- "DOCTYPE is missing"))
- else:
- doctype_name, doctype_system, doctype_pubid = \
- xml_info["DOCTYPE"]
- if doctype_system != metadata_dtd_uri:
- stats["metadata.bad"] += 1
- if doctype_system is None:
- system_problem = "but it is undefined"
- else:
- system_problem = "not '%s'" % doctype_system
- fails["metadata.bad"].append("%s/metadata.xml: "
- "DOCTYPE: SYSTEM should refer to '%s', %s" %
- (x, metadata_dtd_uri, system_problem))
-
- if doctype_name != metadata_doctype_name:
- stats["metadata.bad"] += 1
- fails["metadata.bad"].append("%s/metadata.xml: "
- "DOCTYPE: name should be '%s', not '%s'" %
- (x, metadata_doctype_name, doctype_name))
-
- # load USE flags from metadata.xml
- try:
- musedict = utilities.parse_metadata_use(_metadata_xml)
- except portage.exception.ParseError as e:
- metadata_bad = True
- stats["metadata.bad"] += 1
- fails["metadata.bad"].append("%s/metadata.xml: %s" % (x, e))
- else:
- for atom in chain(*musedict.values()):
- if atom is None:
- continue
- try:
- atom = Atom(atom)
- except InvalidAtom as e:
- stats["metadata.bad"] += 1
- fails["metadata.bad"].append(
- "%s/metadata.xml: Invalid atom: %s" % (x, e))
- else:
- if atom.cp != x:
- stats["metadata.bad"] += 1
- fails["metadata.bad"].append(
- ("%s/metadata.xml: Atom contains "
- "unexpected cat/pn: %s") % (x, atom))
-
- # Run other metadata.xml checkers
- try:
- utilities.check_metadata(_metadata_xml, herd_base)
- except (utilities.UnknownHerdsError, ) as e:
- metadata_bad = True
- stats["metadata.bad"] += 1
- fails["metadata.bad"].append("%s/metadata.xml: %s" % (x, e))
- del e
-
- # Only carry out if in package directory or check forced
- if xmllint_capable and not metadata_bad:
- # xmlint can produce garbage output even on success, so only dump
- # the ouput when it fails.
- st, out = repoman_getstatusoutput(
- "xmllint --nonet --noout --dtdvalid %s %s" % \
- (portage._shell_quote(metadata_dtd),
- portage._shell_quote(os.path.join(checkdir, "metadata.xml"))))
- if st != os.EX_OK:
- print(red("!!!") + " metadata.xml is invalid:")
- for z in out.splitlines():
- print(red("!!! ") + z)
- stats["metadata.bad"] += 1
- fails["metadata.bad"].append(x + "/metadata.xml")
-
- del metadata_bad
- muselist = frozenset(musedict)
-
- changelog_path = os.path.join(checkdir_relative, "ChangeLog")
- changelog_modified = changelog_path in modified_changelogs
-
- # detect unused local USE-descriptions
- used_useflags = set()
-
- for y in ebuildlist:
- relative_path = os.path.join(x, y + ".ebuild")
- full_path = os.path.join(repodir, relative_path)
- ebuild_path = y + ".ebuild"
- if repolevel < 3:
- ebuild_path = os.path.join(pkgdir, ebuild_path)
- if repolevel < 2:
- ebuild_path = os.path.join(catdir, ebuild_path)
- ebuild_path = os.path.join(".", ebuild_path)
- if check_changelog and not changelog_modified \
- and ebuild_path in new_ebuilds:
- stats['changelog.ebuildadded'] += 1
- fails['changelog.ebuildadded'].append(relative_path)
-
- if vcs in ("cvs", "svn", "bzr") and check_ebuild_notadded and y not in eadded:
- # ebuild not added to vcs
- stats["ebuild.notadded"] += 1
- fails["ebuild.notadded"].append(x + "/" + y + ".ebuild")
- myesplit = portage.pkgsplit(y)
- if myesplit is None or myesplit[0] != x.split("/")[-1] \
- or pv_toolong_re.search(myesplit[1]) \
- or pv_toolong_re.search(myesplit[2]):
- stats["ebuild.invalidname"] += 1
- fails["ebuild.invalidname"].append(x + "/" + y + ".ebuild")
- continue
- elif myesplit[0] != pkgdir:
- print(pkgdir, myesplit[0])
- stats["ebuild.namenomatch"] += 1
- fails["ebuild.namenomatch"].append(x + "/" + y + ".ebuild")
- continue
-
- pkg = pkgs[y]
-
- if pkg.invalid:
- allvalid = False
- for k, msgs in pkg.invalid.items():
- for msg in msgs:
- stats[k] += 1
- fails[k].append("%s: %s" % (relative_path, msg))
- continue
-
- myaux = pkg._metadata
- eapi = myaux["EAPI"]
- inherited = pkg.inherited
- live_ebuild = live_eclasses.intersection(inherited)
-
- if repo_config.eapi_is_banned(eapi):
- stats["repo.eapi.banned"] += 1
- fails["repo.eapi.banned"].append(
- "%s: %s" % (relative_path, eapi))
-
- elif repo_config.eapi_is_deprecated(eapi):
- stats["repo.eapi.deprecated"] += 1
- fails["repo.eapi.deprecated"].append(
- "%s: %s" % (relative_path, eapi))
-
- for k, v in myaux.items():
- if not isinstance(v, basestring):
- continue
- m = non_ascii_re.search(v)
- if m is not None:
- stats["variable.invalidchar"] += 1
- fails["variable.invalidchar"].append(
- ("%s: %s variable contains non-ASCII " + \
- "character at position %s") % \
- (relative_path, k, m.start() + 1))
-
- if not src_uri_error:
- # Check that URIs don't reference a server from thirdpartymirrors.
- for uri in portage.dep.use_reduce( \
- myaux["SRC_URI"], matchall=True, is_src_uri=True, eapi=eapi, flat=True):
- contains_mirror = False
- for mirror, mirror_alias in thirdpartymirrors.items():
- if uri.startswith(mirror):
- contains_mirror = True
- break
- if not contains_mirror:
- continue
-
- new_uri = "mirror://%s/%s" % (mirror_alias, uri[len(mirror):])
- stats["SRC_URI.mirror"] += 1
- fails["SRC_URI.mirror"].append(
- "%s: '%s' found in thirdpartymirrors, use '%s'" % \
- (relative_path, mirror, new_uri))
-
- if myaux.get("PROVIDE"):
- stats["virtual.oldstyle"] += 1
- fails["virtual.oldstyle"].append(relative_path)
-
- for pos, missing_var in enumerate(missingvars):
- if not myaux.get(missing_var):
- if catdir == "virtual" and \
- missing_var in ("HOMEPAGE", "LICENSE"):
- continue
- if live_ebuild and missing_var == "KEYWORDS":
- continue
- myqakey = missingvars[pos] + ".missing"
- stats[myqakey] += 1
- fails[myqakey].append(x + "/" + y + ".ebuild")
-
- if catdir == "virtual":
- for var in ("HOMEPAGE", "LICENSE"):
- if myaux.get(var):
- myqakey = var + ".virtual"
- stats[myqakey] += 1
- fails[myqakey].append(relative_path)
-
- # 14 is the length of DESCRIPTION=""
- if len(myaux['DESCRIPTION']) > max_desc_len:
- stats['DESCRIPTION.toolong'] += 1
- fails['DESCRIPTION.toolong'].append(
- "%s: DESCRIPTION is %d characters (max %d)" % \
- (relative_path, len(myaux['DESCRIPTION']), max_desc_len))
-
- keywords = myaux["KEYWORDS"].split()
- if not options.straight_to_stable:
- stable_keywords = []
- for keyword in keywords:
- if not keyword.startswith("~") and \
- not keyword.startswith("-"):
- stable_keywords.append(keyword)
- if stable_keywords:
- if ebuild_path in new_ebuilds and catdir != "virtual":
- stable_keywords.sort()
- stats["KEYWORDS.stable"] += 1
- fails["KEYWORDS.stable"].append(
- relative_path + " added with stable keywords: %s" % \
- " ".join(stable_keywords))
-
- ebuild_archs = set(kw.lstrip("~") for kw in keywords \
- if not kw.startswith("-"))
-
- previous_keywords = slot_keywords.get(pkg.slot)
- if previous_keywords is None:
- slot_keywords[pkg.slot] = set()
- elif ebuild_archs and "*" not in ebuild_archs and not live_ebuild:
- dropped_keywords = previous_keywords.difference(ebuild_archs)
- if dropped_keywords:
- stats["KEYWORDS.dropped"] += 1
- fails["KEYWORDS.dropped"].append(
- relative_path + ": %s" % \
- " ".join(sorted(dropped_keywords)))
-
- slot_keywords[pkg.slot].update(ebuild_archs)
-
- # KEYWORDS="-*" is a stupid replacement for package.mask and screws general KEYWORDS semantics
- if "-*" in keywords:
- haskeyword = False
- for kw in keywords:
- if kw[0] == "~":
- kw = kw[1:]
- if kw in kwlist:
- haskeyword = True
- if not haskeyword:
- stats["KEYWORDS.stupid"] += 1
- fails["KEYWORDS.stupid"].append(x + "/" + y + ".ebuild")
-
- """
- Ebuilds that inherit a "Live" eclass (darcs,subversion,git,cvs,etc..) should
- not be allowed to be marked stable
- """
- if live_ebuild and repo_config.name == "gentoo":
- bad_stable_keywords = []
- for keyword in keywords:
- if not keyword.startswith("~") and \
- not keyword.startswith("-"):
- bad_stable_keywords.append(keyword)
- del keyword
- if bad_stable_keywords:
- stats["LIVEVCS.stable"] += 1
- fails["LIVEVCS.stable"].append(
- x + "/" + y + ".ebuild with stable keywords:%s " % \
- bad_stable_keywords)
- del bad_stable_keywords
-
- if keywords and not has_global_mask(pkg):
- stats["LIVEVCS.unmasked"] += 1
- fails["LIVEVCS.unmasked"].append(relative_path)
-
- if options.ignore_arches:
- arches = [[repoman_settings["ARCH"], repoman_settings["ARCH"],
- repoman_settings["ACCEPT_KEYWORDS"].split()]]
- else:
- arches = set()
- for keyword in keywords:
- if keyword[0] == "-":
- continue
- elif keyword[0] == "~":
- arch = keyword[1:]
- if arch == "*":
- for expanded_arch in profiles:
- if expanded_arch == "**":
- continue
- arches.add((keyword, expanded_arch,
- (expanded_arch, "~" + expanded_arch)))
- else:
- arches.add((keyword, arch, (arch, keyword)))
- else:
- if keyword == "*":
- for expanded_arch in profiles:
- if expanded_arch == "**":
- continue
- arches.add((keyword, expanded_arch,
- (expanded_arch,)))
- else:
- arches.add((keyword, keyword, (keyword,)))
- if not arches:
- # Use an empty profile for checking dependencies of
- # packages that have empty KEYWORDS.
- arches.add(('**', '**', ('**',)))
-
- unknown_pkgs = set()
- baddepsyntax = False
- badlicsyntax = False
- badprovsyntax = False
- catpkg = catdir + "/" + y
-
- inherited_java_eclass = "java-pkg-2" in inherited or \
- "java-pkg-opt-2" in inherited
- inherited_wxwidgets_eclass = "wxwidgets" in inherited
- operator_tokens = set(["||", "(", ")"])
- type_list, badsyntax = [], []
- for mytype in Package._dep_keys + ("LICENSE", "PROPERTIES", "PROVIDE"):
- mydepstr = myaux[mytype]
-
- buildtime = mytype in Package._buildtime_keys
- runtime = mytype in Package._runtime_keys
- token_class = None
- if mytype.endswith("DEPEND"):
- token_class = portage.dep.Atom
-
- try:
- atoms = portage.dep.use_reduce(mydepstr, matchall=1, flat=True, \
- is_valid_flag=pkg.iuse.is_valid_flag, token_class=token_class)
- except portage.exception.InvalidDependString as e:
- atoms = None
- badsyntax.append(str(e))
-
- if atoms and mytype.endswith("DEPEND"):
- if runtime and \
- "test?" in mydepstr.split():
- stats[mytype + '.suspect'] += 1
- fails[mytype + '.suspect'].append(relative_path + \
- ": 'test?' USE conditional in %s" % mytype)
-
- for atom in atoms:
- if atom == "||":
- continue
-
- is_blocker = atom.blocker
-
- # Skip dependency.unknown for blockers, so that we
- # don't encourage people to remove necessary blockers,
- # as discussed in bug 382407. We use atom.without_use
- # due to bug 525376.
- if not is_blocker and \
- not portdb.xmatch("match-all", atom.without_use) and \
- not atom.cp.startswith("virtual/"):
- unknown_pkgs.add((mytype, atom.unevaluated_atom))
-
- if catdir != "virtual":
- if not is_blocker and \
- atom.cp in suspect_virtual:
- stats['virtual.suspect'] += 1
- fails['virtual.suspect'].append(
- relative_path +
- ": %s: consider using '%s' instead of '%s'" %
- (mytype, suspect_virtual[atom.cp], atom))
- if not is_blocker and \
- atom.cp.startswith("perl-core/"):
- stats['dependency.perlcore'] += 1
- fails['dependency.perlcore'].append(
- relative_path +
- ": %s: please use '%s' instead of '%s'" %
- (mytype, atom.replace("perl-core/","virtual/perl-"), atom))
-
- if buildtime and \
- not is_blocker and \
- not inherited_java_eclass and \
- atom.cp == "virtual/jdk":
- stats['java.eclassesnotused'] += 1
- fails['java.eclassesnotused'].append(relative_path)
- elif buildtime and \
- not is_blocker and \
- not inherited_wxwidgets_eclass and \
- atom.cp == "x11-libs/wxGTK":
- stats['wxwidgets.eclassnotused'] += 1
- fails['wxwidgets.eclassnotused'].append(
- (relative_path + ": %ss on x11-libs/wxGTK"
- " without inheriting wxwidgets.eclass") % mytype)
- elif runtime:
- if not is_blocker and \
- atom.cp in suspect_rdepend:
- stats[mytype + '.suspect'] += 1
- fails[mytype + '.suspect'].append(
- relative_path + ": '%s'" % atom)
-
- if atom.operator == "~" and \
- portage.versions.catpkgsplit(atom.cpv)[3] != "r0":
- qacat = 'dependency.badtilde'
- stats[qacat] += 1
- fails[qacat].append(
- (relative_path + ": %s uses the ~ operator"
- " with a non-zero revision:" + \
- " '%s'") % (mytype, atom))
-
- check_missingslot(atom, mytype, eapi, portdb, stats, fails,
- relative_path, myaux)
-
- type_list.extend([mytype] * (len(badsyntax) - len(type_list)))
-
- for m, b in zip(type_list, badsyntax):
- if m.endswith("DEPEND"):
- qacat = "dependency.syntax"
- else:
- qacat = m + ".syntax"
- stats[qacat] += 1
- fails[qacat].append("%s: %s: %s" % (relative_path, m, b))
-
- badlicsyntax = len([z for z in type_list if z == "LICENSE"])
- badprovsyntax = len([z for z in type_list if z == "PROVIDE"])
- baddepsyntax = len(type_list) != badlicsyntax + badprovsyntax
- badlicsyntax = badlicsyntax > 0
- badprovsyntax = badprovsyntax > 0
-
- # uselist checks - global
- myuse = []
- default_use = []
- for myflag in myaux["IUSE"].split():
- flag_name = myflag.lstrip("+-")
- used_useflags.add(flag_name)
- if myflag != flag_name:
- default_use.append(myflag)
- if flag_name not in uselist:
- myuse.append(flag_name)
-
- # uselist checks - metadata
- for mypos in range(len(myuse)-1, -1, -1):
- if myuse[mypos] and (myuse[mypos] in muselist):
- del myuse[mypos]
-
- if default_use and not eapi_has_iuse_defaults(eapi):
- for myflag in default_use:
- stats['EAPI.incompatible'] += 1
- fails['EAPI.incompatible'].append(
- (relative_path + ": IUSE defaults" + \
- " not supported with EAPI='%s':" + \
- " '%s'") % (eapi, myflag))
-
- for mypos in range(len(myuse)):
- stats["IUSE.invalid"] += 1
- fails["IUSE.invalid"].append(x + "/" + y + ".ebuild: %s" % myuse[mypos])
-
- # Check for outdated RUBY targets
- if "ruby-ng" in inherited or "ruby-fakegem" in inherited or "ruby" in inherited:
- ruby_intersection = pkg.iuse.all.intersection(ruby_deprecated)
- if ruby_intersection:
- for myruby in ruby_intersection:
- stats["IUSE.rubydeprecated"] += 1
- fails["IUSE.rubydeprecated"].append(
- (relative_path + ": Deprecated ruby target: %s") % myruby)
-
- # license checks
- if not badlicsyntax:
- # Parse the LICENSE variable, remove USE conditions and
- # flatten it.
- licenses = portage.dep.use_reduce(myaux["LICENSE"], matchall=1, flat=True)
- # Check each entry to ensure that it exists in PORTDIR's
- # license directory.
- for lic in licenses:
- # Need to check for "||" manually as no portage
- # function will remove it without removing values.
- if lic not in liclist and lic != "||":
- stats["LICENSE.invalid"] += 1
- fails["LICENSE.invalid"].append(x + "/" + y + ".ebuild: %s" % lic)
- elif lic in liclist_deprecated:
- stats["LICENSE.deprecated"] += 1
- fails["LICENSE.deprecated"].append("%s: %s" % (relative_path, lic))
-
- # keyword checks
- myuse = myaux["KEYWORDS"].split()
- for mykey in myuse:
- if mykey not in ("-*", "*", "~*"):
- myskey = mykey
- if myskey[:1] == "-":
- myskey = myskey[1:]
- if myskey[:1] == "~":
- myskey = myskey[1:]
- if myskey not in kwlist:
- stats["KEYWORDS.invalid"] += 1
- fails["KEYWORDS.invalid"].append(x + "/" + y + ".ebuild: %s" % mykey)
- elif myskey not in profiles:
- stats["KEYWORDS.invalid"] += 1
- fails["KEYWORDS.invalid"].append(x + "/" + y + ".ebuild: %s (profile invalid)" % mykey)
-
- # restrict checks
- myrestrict = None
- try:
- myrestrict = portage.dep.use_reduce(myaux["RESTRICT"], matchall=1, flat=True)
- except portage.exception.InvalidDependString as e:
- stats["RESTRICT.syntax"] += 1
- fails["RESTRICT.syntax"].append(
- "%s: RESTRICT: %s" % (relative_path, e))
- del e
- if myrestrict:
- myrestrict = set(myrestrict)
- mybadrestrict = myrestrict.difference(valid_restrict)
- if mybadrestrict:
- stats["RESTRICT.invalid"] += len(mybadrestrict)
- for mybad in mybadrestrict:
- fails["RESTRICT.invalid"].append(x + "/" + y + ".ebuild: %s" % mybad)
- # REQUIRED_USE check
- required_use = myaux["REQUIRED_USE"]
- if required_use:
- if not eapi_has_required_use(eapi):
- stats['EAPI.incompatible'] += 1
- fails['EAPI.incompatible'].append(
- relative_path + ": REQUIRED_USE" + \
- " not supported with EAPI='%s'" % (eapi,))
- try:
- portage.dep.check_required_use(required_use, (),
- pkg.iuse.is_valid_flag, eapi=eapi)
- except portage.exception.InvalidDependString as e:
- stats["REQUIRED_USE.syntax"] += 1
- fails["REQUIRED_USE.syntax"].append(
- "%s: REQUIRED_USE: %s" % (relative_path, e))
- del e
-
- # Syntax Checks
- relative_path = os.path.join(x, y + ".ebuild")
- full_path = os.path.join(repodir, relative_path)
- if not vcs_preserves_mtime:
- if ebuild_path not in new_ebuilds and \
- ebuild_path not in modified_ebuilds:
- pkg.mtime = None
- try:
- # All ebuilds should have utf_8 encoding.
- f = io.open(_unicode_encode(full_path,
- encoding=_encodings['fs'], errors='strict'),
- mode='r', encoding=_encodings['repo.content'])
- try:
- for check_name, e in run_checks(f, pkg):
- stats[check_name] += 1
- fails[check_name].append(relative_path + ': %s' % e)
- finally:
- f.close()
- except UnicodeDecodeError:
- # A file.UTF8 failure will have already been recorded above.
- pass
-
- if options.force:
- # The dep_check() calls are the most expensive QA test. If --force
- # is enabled, there's no point in wasting time on these since the
- # user is intent on forcing the commit anyway.
- continue
-
- relevant_profiles = []
- for keyword, arch, groups in arches:
- if arch not in profiles:
- # A missing profile will create an error further down
- # during the KEYWORDS verification.
- continue
-
- if include_arches is not None:
- if arch not in include_arches:
- continue
-
- relevant_profiles.extend((keyword, groups, prof)
- for prof in profiles[arch])
-
- def sort_key(item):
- return item[2].sub_path
-
- relevant_profiles.sort(key=sort_key)
-
- for keyword, groups, prof in relevant_profiles:
-
- if not (prof.status == "stable" or \
- (prof.status == "dev" and options.include_dev) or \
- (prof.status == "exp" and options.include_exp_profiles == 'y')):
- continue
-
- dep_settings = arch_caches.get(prof.sub_path)
- if dep_settings is None:
- dep_settings = portage.config(
- config_profile_path=prof.abs_path,
- config_incrementals=repoman_incrementals,
- config_root=config_root,
- local_config=False,
- _unmatched_removal=options.unmatched_removal,
- env=env, repositories=repoman_settings.repositories)
- dep_settings.categories = repoman_settings.categories
- if options.without_mask:
- dep_settings._mask_manager_obj = \
- copy.deepcopy(dep_settings._mask_manager)
- dep_settings._mask_manager._pmaskdict.clear()
- arch_caches[prof.sub_path] = dep_settings
-
- xmatch_cache_key = (prof.sub_path, tuple(groups))
- xcache = arch_xmatch_caches.get(xmatch_cache_key)
- if xcache is None:
- portdb.melt()
- portdb.freeze()
- xcache = portdb.xcache
- xcache.update(shared_xmatch_caches)
- arch_xmatch_caches[xmatch_cache_key] = xcache
-
- trees[root]["porttree"].settings = dep_settings
- portdb.settings = dep_settings
- portdb.xcache = xcache
-
- dep_settings["ACCEPT_KEYWORDS"] = " ".join(groups)
- # just in case, prevent config.reset() from nuking these.
- dep_settings.backup_changes("ACCEPT_KEYWORDS")
-
- # This attribute is used in dbapi._match_use() to apply
- # use.stable.{mask,force} settings based on the stable
- # status of the parent package. This is required in order
- # for USE deps of unstable packages to be resolved correctly,
- # since otherwise use.stable.{mask,force} settings of
- # dependencies may conflict (see bug #456342).
- dep_settings._parent_stable = dep_settings._isStable(pkg)
-
- # Handle package.use*.{force,mask) calculation, for use
- # in dep_check.
- dep_settings.useforce = dep_settings._use_manager.getUseForce(
- pkg, stable=dep_settings._parent_stable)
- dep_settings.usemask = dep_settings._use_manager.getUseMask(
- pkg, stable=dep_settings._parent_stable)
-
- if not baddepsyntax:
- ismasked = not ebuild_archs or \
- pkg.cpv not in portdb.xmatch("match-visible",
- Atom("%s::%s" % (pkg.cp, repo_config.name)))
- if ismasked:
- if not have_pmasked:
- have_pmasked = bool(dep_settings._getMaskAtom(
- pkg.cpv, pkg._metadata))
- if options.ignore_masked:
- continue
- # we are testing deps for a masked package; give it some lee-way
- suffix = "masked"
- matchmode = "minimum-all"
- else:
- suffix = ""
- matchmode = "minimum-visible"
-
- if not have_dev_keywords:
- have_dev_keywords = \
- bool(dev_keywords.intersection(keywords))
-
- if prof.status == "dev":
- suffix = suffix + "indev"
-
- for mytype in Package._dep_keys:
-
- mykey = "dependency.bad" + suffix
- myvalue = myaux[mytype]
- if not myvalue:
- continue
-
- success, atoms = portage.dep_check(myvalue, portdb,
- dep_settings, use="all", mode=matchmode,
- trees=trees)
-
- if success:
- if atoms:
-
- # Don't bother with dependency.unknown for
- # cases in which *DEPEND.bad is triggered.
- for atom in atoms:
- # dep_check returns all blockers and they
- # aren't counted for *DEPEND.bad, so we
- # ignore them here.
- if not atom.blocker:
- unknown_pkgs.discard(
- (mytype, atom.unevaluated_atom))
-
- if not prof.sub_path:
- # old-style virtuals currently aren't
- # resolvable with empty profile, since
- # 'virtuals' mappings are unavailable
- # (it would be expensive to search
- # for PROVIDE in all ebuilds)
- atoms = [atom for atom in atoms if not \
- (atom.cp.startswith('virtual/') and \
- not portdb.cp_list(atom.cp))]
-
- # we have some unsolvable deps
- # remove ! deps, which always show up as unsatisfiable
- atoms = [str(atom.unevaluated_atom) \
- for atom in atoms if not atom.blocker]
-
- # if we emptied out our list, continue:
- if not atoms:
- continue
- stats[mykey] += 1
- fails[mykey].append("%s: %s: %s(%s)\n%s" % \
- (relative_path, mytype, keyword,
- prof, pformat(atoms, indent=6)))
- else:
- stats[mykey] += 1
- fails[mykey].append("%s: %s: %s(%s)\n%s" % \
- (relative_path, mytype, keyword,
- prof, pformat(atoms, indent=6)))
-
- if not baddepsyntax and unknown_pkgs:
- type_map = {}
- for mytype, atom in unknown_pkgs:
- type_map.setdefault(mytype, set()).add(atom)
- for mytype, atoms in type_map.items():
- stats["dependency.unknown"] += 1
- fails["dependency.unknown"].append("%s: %s: %s" %
- (relative_path, mytype, ", ".join(sorted(atoms))))
-
- # check if there are unused local USE-descriptions in metadata.xml
- # (unless there are any invalids, to avoid noise)
- if allvalid:
- for myflag in muselist.difference(used_useflags):
- stats["metadata.warning"] += 1
- fails["metadata.warning"].append(
- "%s/metadata.xml: unused local USE-description: '%s'" % \
- (x, myflag))
-
- if options.if_modified == "y" and len(effective_scanlist) < 1:
- logging.warning("--if-modified is enabled, but no modified packages were found!")
-
- if options.mode == "manifest":
- sys.exit(dofail)
-
- # dofail will be set to 1 if we have failed in at least one non-warning category
- dofail = 0
- # 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 = options.mode != 'full'
-
- for x in qacats:
- if not stats[x]:
- continue
- 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 = io.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_outputs = {
- 'column': utilities.format_qa_output_column,
- 'default': utilities.format_qa_output
- }
-
- format_output = format_outputs.get(options.output_style,
- format_outputs['default'])
- format_output(f, stats, fails, dofull, dofail, options, qawarnings)
-
- style_file.flush()
- del console_writer, f, style_file
- qa_output = qa_output.getvalue()
- qa_output = qa_output.splitlines(True)
-
- suggest_ignore_masked = False
- suggest_include_dev = False
-
- if have_pmasked and not (options.without_mask or options.ignore_masked):
- suggest_ignore_masked = True
- if have_dev_keywords and not options.include_dev:
- suggest_include_dev = True
-
- if suggest_ignore_masked or suggest_include_dev:
- print()
- if suggest_ignore_masked:
- print(bold("Note: use --without-mask to check " + \
- "KEYWORDS on dependencies of masked packages"))
-
- if suggest_include_dev:
- print(bold("Note: use --include-dev (-d) to check " + \
- "dependencies for 'dev' profiles"))
- print()
-
- if options.mode != 'commit':
- if dofull:
- print(bold("Note: type \"repoman full\" for a complete listing."))
- if dowarn and not dofail:
- print(green("RepoMan sez:"),"\"You're only giving me a partial QA payment?\n I'll take it this time, but I'm not happy.\"")
- elif not dofail:
- print(green("RepoMan sez:"),"\"If everyone were like you, I'd be out of business!\"")
- elif dofail:
- print(bad("Please fix these important QA issues first."))
- print(green("RepoMan sez:"),"\"Make your QA payment on time and you'll never see the likes of me.\"\n")
+ repoman_main(sys.argv[1:])
+ except IOError as e:
+ if e.errno == errno.EACCES:
+ print("\nRepoman: Need user access")
sys.exit(1)
- else:
- if dofail and can_force and options.force and not options.pretend:
- print(green("RepoMan sez:") + \
- " \"You want to commit even with these QA issues?\n" + \
- " I'll take it this time, but I'm not happy.\"\n")
- elif dofail:
- if options.force and not can_force:
- print(bad("The --force option has been disabled due to extraordinary issues."))
- print(bad("Please fix these important QA issues first."))
- print(green("RepoMan sez:"),"\"Make your QA payment on time and you'll never see the likes of me.\"\n")
- sys.exit(1)
-
- if options.pretend:
- print(green("RepoMan sez:"), "\"So, you want to play it safe. Good call.\"\n")
-
- myunadded = []
- if vcs == "cvs":
- try:
- myvcstree = portage.cvstree.getentries("./", recursive=1)
- myunadded = portage.cvstree.findunadded(myvcstree, recursive=1, basedir="./")
- except SystemExit as e:
- raise # TODO propagate this
- except:
- err("Error retrieving CVS tree; exiting.")
- if vcs == "svn":
- try:
- with repoman_popen("svn status --no-ignore") as f:
- svnstatus = f.readlines()
- myunadded = ["./" + elem.rstrip().split()[1] for elem in svnstatus if elem.startswith("?") or elem.startswith("I")]
- except SystemExit as e:
- raise # TODO propagate this
- except:
- err("Error retrieving SVN info; exiting.")
- if vcs == "git":
- # get list of files not under version control or missing
- myf = repoman_popen("git ls-files --others")
- myunadded = ["./" + elem[:-1] for elem in myf]
- myf.close()
- if vcs == "bzr":
- try:
- with repoman_popen("bzr status -S .") as f:
- bzrstatus = f.readlines()
- myunadded = ["./" + elem.rstrip().split()[1].split('/')[-1:][0] for elem in bzrstatus if elem.startswith("?") or elem[0:2] == " D"]
- except SystemExit as e:
- raise # TODO propagate this
- except:
- err("Error retrieving bzr info; exiting.")
- if vcs == "hg":
- with repoman_popen("hg status --no-status --unknown .") as f:
- myunadded = f.readlines()
- myunadded = ["./" + elem.rstrip() for elem in myunadded]
-
- # Mercurial doesn't handle manually deleted files as removed from
- # the repository, so the user need to remove them before commit,
- # using "hg remove [FILES]"
- with repoman_popen("hg status --no-status --deleted .") as f:
- mydeleted = f.readlines()
- mydeleted = ["./" + elem.rstrip() for elem in mydeleted]
-
-
- myautoadd = []
- if myunadded:
- for x in range(len(myunadded)-1, -1, -1):
- xs = myunadded[x].split("/")
- if xs[-1] == "files":
- print("!!! files dir is not added! Please correct this.")
- sys.exit(-1)
- elif xs[-1] == "Manifest":
- # It's a manifest... auto add
- myautoadd += [myunadded[x]]
- del myunadded[x]
-
- if myunadded:
- print(red("!!! The following files are in your local tree but are not added to the master"))
- print(red("!!! tree. Please remove them from the local tree or add them to the master tree."))
- for x in myunadded:
- print(" ", x)
- print()
- print()
- sys.exit(1)
-
- if vcs == "hg" and mydeleted:
- print(red("!!! The following files are removed manually from your local tree but are not"))
- print(red("!!! removed from the repository. Please remove them, using \"hg remove [FILES]\"."))
- for x in mydeleted:
- print(" ", x)
- print()
- print()
- sys.exit(1)
-
- if vcs == "cvs":
- mycvstree = cvstree.getentries("./", recursive=1)
- mychanged = cvstree.findchanged(mycvstree, recursive=1, basedir="./")
- mynew = cvstree.findnew(mycvstree, recursive=1, basedir="./")
- myremoved = portage.cvstree.findremoved(mycvstree, recursive=1, basedir="./")
- bin_blob_pattern = re.compile("^-kb$")
- no_expansion = set(portage.cvstree.findoption(mycvstree, bin_blob_pattern,
- recursive=1, basedir="./"))
-
- if vcs == "svn":
- with repoman_popen("svn status") as f:
- svnstatus = f.readlines()
- mychanged = ["./" + elem.split()[-1:][0] for elem in svnstatus if (elem[:1] in "MR" or elem[1:2] in "M")]
- mynew = ["./" + elem.split()[-1:][0] for elem in svnstatus if elem.startswith("A")]
- myremoved = ["./" + elem.split()[-1:][0] for elem in svnstatus if elem.startswith("D")]
-
- # Subversion expands keywords specified in svn:keywords properties.
- with repoman_popen("svn propget -R svn:keywords") as f:
- props = f.readlines()
- expansion = dict(("./" + prop.split(" - ")[0], prop.split(" - ")[1].split()) \
- for prop in props if " - " in prop)
-
- elif vcs == "git":
- with repoman_popen("git diff-index --name-only "
- "--relative --diff-filter=M HEAD") as f:
- mychanged = f.readlines()
- mychanged = ["./" + elem[:-1] for elem in mychanged]
-
- with repoman_popen("git diff-index --name-only "
- "--relative --diff-filter=A HEAD") as f:
- mynew = f.readlines()
- mynew = ["./" + elem[:-1] for elem in mynew]
-
- with repoman_popen("git diff-index --name-only "
- "--relative --diff-filter=D HEAD") as f:
- myremoved = f.readlines()
- myremoved = ["./" + elem[:-1] for elem in myremoved]
-
- if vcs == "bzr":
- with repoman_popen("bzr status -S .") as f:
- bzrstatus = f.readlines()
- mychanged = ["./" + elem.split()[-1:][0].split('/')[-1:][0] for elem in bzrstatus if elem and elem[1:2] == "M"]
- mynew = ["./" + elem.split()[-1:][0].split('/')[-1:][0] for elem in bzrstatus if elem and (elem[1:2] in "NK" or elem[0:1] == "R")]
- myremoved = ["./" + elem.split()[-1:][0].split('/')[-1:][0] for elem in bzrstatus if elem.startswith("-")]
- myremoved = ["./" + elem.split()[-3:-2][0].split('/')[-1:][0] for elem in bzrstatus if elem and (elem[1:2] == "K" or elem[0:1] == "R")]
- # Bazaar expands nothing.
-
- if vcs == "hg":
- with repoman_popen("hg status --no-status --modified .") as f:
- mychanged = f.readlines()
- mychanged = ["./" + elem.rstrip() for elem in mychanged]
-
- with repoman_popen("hg status --no-status --added .") as f:
- mynew = f.readlines()
- mynew = ["./" + elem.rstrip() for elem in mynew]
-
- with repoman_popen("hg status --no-status --removed .") as f:
- myremoved = f.readlines()
- myremoved = ["./" + elem.rstrip() for elem in myremoved]
-
- if vcs:
- if not (mychanged or mynew or myremoved or (vcs == "hg" and mydeleted)):
- print(green("RepoMan sez:"), "\"Doing nothing is not always good for QA.\"")
- print()
- print("(Didn't find any changed files...)")
- print()
- sys.exit(1)
-
- # Manifests need to be regenerated after all other commits, so don't commit
- # them now even if they have changed.
- mymanifests = set()
- myupdates = set()
- for f in mychanged + mynew:
- if "Manifest" == os.path.basename(f):
- mymanifests.add(f)
- else:
- myupdates.add(f)
- myupdates.difference_update(myremoved)
- myupdates = list(myupdates)
- mymanifests = list(mymanifests)
- myheaders = []
- mydirty = []
-
- commitmessage = options.commitmsg
- if options.commitmsgfile:
- try:
- f = io.open(_unicode_encode(options.commitmsgfile,
- encoding=_encodings['fs'], errors='strict'),
- mode='r', encoding=_encodings['content'], errors='replace')
- commitmessage = f.read()
- f.close()
- del f
- except (IOError, OSError) as e:
- if e.errno == errno.ENOENT:
- portage.writemsg("!!! File Not Found: --commitmsgfile='%s'\n" % options.commitmsgfile)
- else:
- raise
- # We've read the content so the file is no longer needed.
- commitmessagefile = None
- if not commitmessage or not commitmessage.strip():
- try:
- editor = os.environ.get("EDITOR")
- if editor and utilities.editor_is_executable(editor):
- commitmessage = utilities.get_commit_message_with_editor(
- editor, message=qa_output)
- else:
- commitmessage = utilities.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()
- changelog_msg = commitmessage
- portage_version = getattr(portage, "VERSION", None)
- gpg_key = repoman_settings.get("PORTAGE_GPG_KEY", "")
- dco_sob = repoman_settings.get("DCO_SIGNED_OFF_BY", "")
- if portage_version is None:
- sys.stderr.write("Failed to insert portage version in message!\n")
- sys.stderr.flush()
- portage_version = "Unknown"
-
- report_options = []
- if options.force:
- report_options.append("--force")
- if options.ignore_arches:
- report_options.append("--ignore-arches")
- if include_arches is not None:
- report_options.append("--include-arches=\"%s\"" %
- " ".join(sorted(include_arches)))
-
- if vcs == "git":
- # Use new footer only for git (see bug #438364).
- commit_footer = "\n\nPackage-Manager: portage-%s" % portage_version
- if report_options:
- commit_footer += "\nRepoMan-Options: " + " ".join(report_options)
- if sign_manifests:
- commit_footer += "\nManifest-Sign-Key: %s" % (gpg_key, )
- if dco_sob:
- commit_footer += "\nSigned-off-by: %s" % (dco_sob, )
- else:
- unameout = platform.system() + " "
- if platform.system() in ["Darwin", "SunOS"]:
- unameout += platform.processor()
- else:
- unameout += platform.machine()
- commit_footer = "\n\n"
- if dco_sob:
- commit_footer += "Signed-off-by: %s\n" % (dco_sob, )
- commit_footer += "(Portage version: %s/%s/%s" % \
- (portage_version, vcs, unameout)
- if report_options:
- commit_footer += ", RepoMan options: " + " ".join(report_options)
- if sign_manifests:
- commit_footer += ", signed Manifest commit with key %s" % \
- (gpg_key, )
- else:
- commit_footer += ", unsigned Manifest commit"
- commit_footer += ")"
-
- commitmessage += commit_footer
-
- broken_changelog_manifests = []
- if options.echangelog in ('y', 'force'):
- logging.info("checking for unmodified ChangeLog files")
- committer_name = utilities.get_committer_name(env=repoman_settings)
- for x in sorted(vcs_files_to_cps(
- chain(myupdates, mymanifests, myremoved))):
- catdir, pkgdir = x.split("/")
- checkdir = repodir + "/" + x
- checkdir_relative = ""
- if repolevel < 3:
- checkdir_relative = os.path.join(pkgdir, checkdir_relative)
- if repolevel < 2:
- checkdir_relative = os.path.join(catdir, checkdir_relative)
- checkdir_relative = os.path.join(".", checkdir_relative)
-
- changelog_path = os.path.join(checkdir_relative, "ChangeLog")
- changelog_modified = changelog_path in modified_changelogs
- if changelog_modified and options.echangelog != 'force':
- continue
-
- # get changes for this package
- cdrlen = len(checkdir_relative)
- clnew = [elem[cdrlen:] for elem in mynew if elem.startswith(checkdir_relative)]
- clremoved = [elem[cdrlen:] for elem in myremoved if elem.startswith(checkdir_relative)]
- clchanged = [elem[cdrlen:] for elem in mychanged if elem.startswith(checkdir_relative)]
-
- # Skip ChangeLog generation if only the Manifest was modified,
- # as discussed in bug #398009.
- nontrivial_cl_files = set()
- nontrivial_cl_files.update(clnew, clremoved, clchanged)
- nontrivial_cl_files.difference_update(['Manifest'])
- if not nontrivial_cl_files and options.echangelog != 'force':
- continue
-
- new_changelog = utilities.UpdateChangeLog(checkdir_relative,
- committer_name, changelog_msg,
- os.path.join(repodir, 'skel.ChangeLog'),
- catdir, pkgdir,
- new=clnew, removed=clremoved, changed=clchanged,
- pretend=options.pretend)
- if new_changelog is None:
- writemsg_level("!!! Updating the ChangeLog failed\n", \
- level=logging.ERROR, noiselevel=-1)
- sys.exit(1)
-
- # if the ChangeLog was just created, add it to vcs
- if new_changelog:
- myautoadd.append(changelog_path)
- # myautoadd is appended to myupdates below
- else:
- myupdates.append(changelog_path)
-
- if options.ask and not options.pretend:
- # regenerate Manifest for modified ChangeLog (bug #420735)
- repoman_settings["O"] = checkdir
- digestgen(mysettings=repoman_settings, myportdb=portdb)
- else:
- broken_changelog_manifests.append(x)
-
- if myautoadd:
- print(">>> Auto-Adding missing Manifest/ChangeLog file(s)...")
- add_cmd = [vcs, "add"]
- add_cmd += myautoadd
- if options.pretend:
- portage.writemsg_stdout("(%s)\n" % " ".join(add_cmd),
- noiselevel=-1)
- else:
-
- if sys.hexversion < 0x3020000 and sys.hexversion >= 0x3000000 and \
- not os.path.isabs(add_cmd[0]):
- # Python 3.1 _execvp throws TypeError for non-absolute executable
- # path passed as bytes (see http://bugs.python.org/issue8513).
- fullname = find_binary(add_cmd[0])
- if fullname is None:
- raise portage.exception.CommandNotFound(add_cmd[0])
- add_cmd[0] = fullname
-
- add_cmd = [_unicode_encode(arg) for arg in add_cmd]
- retcode = subprocess.call(add_cmd)
- if retcode != os.EX_OK:
- logging.error(
- "Exiting on %s error code: %s\n" % (vcs, retcode))
- sys.exit(retcode)
-
- myupdates += myautoadd
-
- print("* %s files being committed..." % green(str(len(myupdates))), end=' ')
-
- if vcs not in ('cvs', 'svn'):
- # With git, bzr and hg, there's never any keyword expansion, so
- # there's no need to regenerate manifests and all files will be
- # committed in one big commit at the end.
- print()
- elif not repo_config.thin_manifest:
- if vcs == 'cvs':
- headerstring = "'\$(Header|Id).*\$'"
- elif vcs == "svn":
- svn_keywords = dict((k.lower(), k) for k in [
- "Rev",
- "Revision",
- "LastChangedRevision",
- "Date",
- "LastChangedDate",
- "Author",
- "LastChangedBy",
- "URL",
- "HeadURL",
- "Id",
- "Header",
- ])
-
- for myfile in myupdates:
-
- # for CVS, no_expansion contains files that are excluded from expansion
- if vcs == "cvs":
- if myfile in no_expansion:
- continue
-
- # for SVN, expansion contains files that are included in expansion
- elif vcs == "svn":
- if myfile not in expansion:
- continue
-
- # Subversion keywords are case-insensitive in svn:keywords properties, but case-sensitive in contents of files.
- enabled_keywords = []
- for k in expansion[myfile]:
- keyword = svn_keywords.get(k.lower())
- if keyword is not None:
- enabled_keywords.append(keyword)
-
- headerstring = "'\$(%s).*\$'" % "|".join(enabled_keywords)
-
- myout = repoman_getstatusoutput("egrep -q " + headerstring + " " +
- portage._shell_quote(myfile))
- if myout[0] == 0:
- myheaders.append(myfile)
-
- print("%s have headers that will change." % green(str(len(myheaders))))
- print("* Files with headers will cause the manifests to be changed and committed separately.")
-
- logging.info("myupdates: %s", myupdates)
- logging.info("myheaders: %s", myheaders)
-
- uq = UserQuery(options)
- if options.ask and uq.query('Commit changes?', True) != 'Yes':
- print("* aborting commit.")
- sys.exit(128 + signal.SIGINT)
-
- # Handle the case where committed files have keywords which
- # will change and need a priming commit before the Manifest
- # can be committed.
- if (myupdates or myremoved) and myheaders:
- myfiles = myupdates + myremoved
- fd, commitmessagefile = tempfile.mkstemp(".repoman.msg")
- mymsg = os.fdopen(fd, "wb")
- mymsg.write(_unicode_encode(commitmessage))
- mymsg.close()
-
- print()
- print(green("Using commit message:"))
- print(green("------------------------------------------------------------------------------"))
- print(commitmessage)
- print(green("------------------------------------------------------------------------------"))
- print()
-
- # Having a leading ./ prefix on file paths can trigger a bug in
- # the cvs server when committing files to multiple directories,
- # so strip the prefix.
- myfiles = [f.lstrip("./") for f in myfiles]
-
- commit_cmd = [vcs]
- commit_cmd.extend(vcs_global_opts)
- commit_cmd.append("commit")
- commit_cmd.extend(vcs_local_opts)
- commit_cmd.extend(["-F", commitmessagefile])
- commit_cmd.extend(myfiles)
-
- try:
- if options.pretend:
- print("(%s)" % (" ".join(commit_cmd),))
- else:
- retval = spawn(commit_cmd, env=commit_env)
- if retval != os.EX_OK:
- writemsg_level(("!!! Exiting on %s (shell) " + \
- "error code: %s\n") % (vcs, retval),
- level=logging.ERROR, noiselevel=-1)
- sys.exit(retval)
- finally:
- try:
- os.unlink(commitmessagefile)
- except OSError:
- pass
-
- # Setup the GPG commands
- def gpgsign(filename):
- gpgcmd = repoman_settings.get("PORTAGE_GPG_SIGNING_COMMAND")
- if gpgcmd in [None, '']:
- raise MissingParameter("PORTAGE_GPG_SIGNING_COMMAND is unset!" + \
- " Is make.globals missing?")
- if "${PORTAGE_GPG_KEY}" in gpgcmd and \
- "PORTAGE_GPG_KEY" not in repoman_settings:
- raise MissingParameter("PORTAGE_GPG_KEY is unset!")
- if "${PORTAGE_GPG_DIR}" in gpgcmd:
- if "PORTAGE_GPG_DIR" not in repoman_settings:
- repoman_settings["PORTAGE_GPG_DIR"] = \
- os.path.expanduser("~/.gnupg")
- logging.info("Automatically setting PORTAGE_GPG_DIR to '%s'" \
- % repoman_settings["PORTAGE_GPG_DIR"])
- else:
- repoman_settings["PORTAGE_GPG_DIR"] = \
- os.path.expanduser(repoman_settings["PORTAGE_GPG_DIR"])
- if not os.access(repoman_settings["PORTAGE_GPG_DIR"], os.X_OK):
- raise portage.exception.InvalidLocation(
- "Unable to access directory: PORTAGE_GPG_DIR='%s'" % \
- repoman_settings["PORTAGE_GPG_DIR"])
- gpgvars = {"FILE": filename}
- for k in ("PORTAGE_GPG_DIR", "PORTAGE_GPG_KEY"):
- v = repoman_settings.get(k)
- if v is not None:
- gpgvars[k] = v
- gpgcmd = portage.util.varexpand(gpgcmd, mydict=gpgvars)
- if options.pretend:
- print("(" + gpgcmd + ")")
- else:
- # Encode unicode manually for bug #310789.
- gpgcmd = portage.util.shlex_split(gpgcmd)
-
- if sys.hexversion < 0x3020000 and sys.hexversion >= 0x3000000 and \
- not os.path.isabs(gpgcmd[0]):
- # Python 3.1 _execvp throws TypeError for non-absolute executable
- # path passed as bytes (see http://bugs.python.org/issue8513).
- fullname = find_binary(gpgcmd[0])
- if fullname is None:
- raise portage.exception.CommandNotFound(gpgcmd[0])
- gpgcmd[0] = fullname
-
- gpgcmd = [_unicode_encode(arg,
- encoding=_encodings['fs'], errors='strict') for arg in gpgcmd]
- rValue = subprocess.call(gpgcmd)
- if rValue == os.EX_OK:
- os.rename(filename + ".asc", filename)
- else:
- raise portage.exception.PortageException("!!! gpg exited with '" + str(rValue) + "' status")
-
- def need_signature(filename):
- try:
- with open(_unicode_encode(filename,
- encoding=_encodings['fs'], errors='strict'), 'rb') as f:
- return b"BEGIN PGP SIGNED MESSAGE" not in f.readline()
- except IOError as e:
- if e.errno in (errno.ENOENT, errno.ESTALE):
- return False
- raise
-
- # When files are removed and re-added, the cvs server will put /Attic/
- # inside the $Header path. This code detects the problem and corrects it
- # so that the Manifest will generate correctly. See bug #169500.
- # Use binary mode in order to avoid potential character encoding issues.
- cvs_header_re = re.compile(br'^#\s*\$Header.*\$$')
- attic_str = b'/Attic/'
- attic_replace = b'/'
- for x in myheaders:
- f = open(_unicode_encode(x,
- encoding=_encodings['fs'], errors='strict'),
- mode='rb')
- mylines = f.readlines()
- f.close()
- modified = False
- for i, line in enumerate(mylines):
- if cvs_header_re.match(line) is not None and \
- attic_str in line:
- mylines[i] = line.replace(attic_str, attic_replace)
- modified = True
- if modified:
- portage.util.write_atomic(x, b''.join(mylines),
- mode='wb')
-
- if repolevel == 1:
- print(green("RepoMan sez:"), "\"You're rather crazy... "
- "doing the entire repository.\"\n")
-
- if vcs in ('cvs', 'svn') and (myupdates or myremoved):
-
- for x in sorted(vcs_files_to_cps(
- chain(myupdates, myremoved, mymanifests))):
- repoman_settings["O"] = os.path.join(repodir, x)
- digestgen(mysettings=repoman_settings, myportdb=portdb)
-
- elif broken_changelog_manifests:
- for x in broken_changelog_manifests:
- repoman_settings["O"] = os.path.join(repodir, x)
- digestgen(mysettings=repoman_settings, myportdb=portdb)
-
- signed = False
- if sign_manifests:
- signed = True
- try:
- for x in sorted(vcs_files_to_cps(
- chain(myupdates, myremoved, mymanifests))):
- repoman_settings["O"] = os.path.join(repodir, x)
- manifest_path = os.path.join(repoman_settings["O"], "Manifest")
- if not need_signature(manifest_path):
- continue
- gpgsign(manifest_path)
- except portage.exception.PortageException as e:
- portage.writemsg("!!! %s\n" % str(e))
- portage.writemsg("!!! Disabled FEATURES='sign'\n")
- signed = False
-
- if vcs == 'git':
- # It's not safe to use the git commit -a option since there might
- # be some modified files elsewhere in the working tree that the
- # user doesn't want to commit. Therefore, call git update-index
- # in order to ensure that the index is updated with the latest
- # versions of all new and modified files in the relevant portion
- # of the working tree.
- myfiles = mymanifests + myupdates
- myfiles.sort()
- update_index_cmd = ["git", "update-index"]
- update_index_cmd.extend(f.lstrip("./") for f in myfiles)
- if options.pretend:
- print("(%s)" % (" ".join(update_index_cmd),))
- else:
- retval = spawn(update_index_cmd, env=os.environ)
- if retval != os.EX_OK:
- writemsg_level(("!!! Exiting on %s (shell) " + \
- "error code: %s\n") % (vcs, retval),
- level=logging.ERROR, noiselevel=-1)
- sys.exit(retval)
-
- if True:
- myfiles = mymanifests[:]
- # If there are no header (SVN/CVS keywords) changes in
- # the files, this Manifest commit must include the
- # other (yet uncommitted) files.
- if not myheaders:
- myfiles += myupdates
- myfiles += myremoved
- myfiles.sort()
-
- fd, commitmessagefile = tempfile.mkstemp(".repoman.msg")
- mymsg = os.fdopen(fd, "wb")
- mymsg.write(_unicode_encode(commitmessage))
- mymsg.close()
-
- commit_cmd = []
- if options.pretend and vcs is None:
- # substitute a bogus value for pretend output
- commit_cmd.append("cvs")
- else:
- commit_cmd.append(vcs)
- commit_cmd.extend(vcs_global_opts)
- commit_cmd.append("commit")
- commit_cmd.extend(vcs_local_opts)
- if vcs == "hg":
- commit_cmd.extend(["--logfile", commitmessagefile])
- commit_cmd.extend(myfiles)
- else:
- commit_cmd.extend(["-F", commitmessagefile])
- commit_cmd.extend(f.lstrip("./") for f in myfiles)
-
- try:
- if options.pretend:
- print("(%s)" % (" ".join(commit_cmd),))
- else:
- retval = spawn(commit_cmd, env=commit_env)
- if retval != os.EX_OK:
- if repo_config.sign_commit and vcs == 'git' and \
- not git_supports_gpg_sign():
- # Inform user that newer git is needed (bug #403323).
- logging.error(
- "Git >=1.7.9 is required for signed commits!")
-
- writemsg_level(("!!! Exiting on %s (shell) " + \
- "error code: %s\n") % (vcs, retval),
- level=logging.ERROR, noiselevel=-1)
- sys.exit(retval)
- finally:
- try:
- os.unlink(commitmessagefile)
- except OSError:
- pass
-
- print()
- if vcs:
- print("Commit complete.")
else:
- print("repoman was too scared by not seeing any familiar version control file that he forgot to commit anything")
- print(green("RepoMan sez:"), "\"If everyone were like you, I'd be out of business!\"\n")
- sys.exit(0)
+ raise
diff --cc bin/save-ebuild-env.sh
index 599d6ea,ddef1fd..28162d1
--- a/bin/save-ebuild-env.sh
+++ b/bin/save-ebuild-env.sh
@@@ -88,8 -89,9 +89,12 @@@ __save_ebuild_env()
___eapi_has_package_manager_build_user && unset -f package_manager_build_user
___eapi_has_package_manager_build_group && unset -f package_manager_build_group
- # Clear out the triple underscore namespace as it is reserved by the PM.
- unset -f $(compgen -A function ___)
- unset ${!___*}
+ # PREFIX: compgen is not compiled in during bootstrap
- type compgen >& /dev/null && unset -f $(compgen -A function ___eapi_)
++ if type compgen >& /dev/null ; then
++ # Clear out the triple underscore namespace as it is reserved by the PM.
++ unset -f $(compgen -A function ___)
++ unset ${!___*}
++ fi
# portage config variables and variables set directly by portage
unset ACCEPT_LICENSE BAD BRACKET BUILD_PREFIX COLS \
diff --cc pym/_emerge/actions.py
index 3218cde,59626ad..1d324aa
--- a/pym/_emerge/actions.py
+++ b/pym/_emerge/actions.py
@@@ -2376,39 -2412,34 +2418,40 @@@ def getgccversion(chost=None)
"!!! other terminals also.\n"
)
+ def getclangversion(output):
+ version = re.search('clang version ([0-9.]+) ', output)
+ if version:
+ return version.group(1)
+ return "unknown"
+
- try:
- proc = subprocess.Popen([ubinpath + "/gcc-config", "-c"],
- stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- except OSError:
- myoutput = None
- mystatus = 1
- else:
- myoutput = _unicode_decode(proc.communicate()[0]).rstrip("\n")
- mystatus = proc.wait()
- if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
- return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
+ if chost:
+ try:
+ proc = subprocess.Popen(["gcc-config", "-c"],
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ except OSError:
+ myoutput = None
+ mystatus = 1
+ else:
+ myoutput = _unicode_decode(proc.communicate()[0]).rstrip("\n")
+ mystatus = proc.wait()
+ if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
+ return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
- try:
- proc = subprocess.Popen(
- [ubinpath + "/" + chost + "-" + gcc_ver_command[0]] + gcc_ver_command[1:],
- stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- except OSError:
- myoutput = None
- mystatus = 1
- else:
- myoutput = _unicode_decode(proc.communicate()[0]).rstrip("\n")
- mystatus = proc.wait()
- if mystatus == os.EX_OK:
- return gcc_ver_prefix + myoutput
+ try:
+ proc = subprocess.Popen(
+ [chost + "-" + gcc_ver_command[0]] + gcc_ver_command[1:],
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ except OSError:
+ myoutput = None
+ mystatus = 1
+ else:
+ myoutput = _unicode_decode(proc.communicate()[0]).rstrip("\n")
+ mystatus = proc.wait()
+ if mystatus == os.EX_OK:
+ return gcc_ver_prefix + myoutput
try:
- proc = subprocess.Popen(gcc_ver_command,
+ proc = subprocess.Popen([ubinpath + "/" + gcc_ver_command[0]] + gcc_ver_command[1:],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError:
myoutput = None
diff --cc pym/portage/dbapi/vartree.py
index f4c7cdc,e7effca..670221f
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@@ -35,12 -35,9 +35,12 @@@ portage.proxy.lazyimport.lazyimport(glo
'portage.util.movefile:movefile',
'portage.util.path:first_existing,iter_parents',
'portage.util.writeable_check:get_ro_checker',
- 'portage.util:xattr@_xattr',
+ 'portage.util._xattr:xattr',
'portage.util._dyn_libs.PreservedLibsRegistry:PreservedLibsRegistry',
'portage.util._dyn_libs.LinkageMapELF:LinkageMapELF@LinkageMap',
+ 'portage.util._dyn_libs.LinkageMapMachO:LinkageMapMachO',
+ 'portage.util._dyn_libs.LinkageMapPeCoff:LinkageMapPeCoff',
+ 'portage.util._dyn_libs.LinkageMapXCoff:LinkageMapXCoff',
'portage.util._async.SchedulerInterface:SchedulerInterface',
'portage.util._eventloop.EventLoop:EventLoop',
'portage.util._eventloop.global_event_loop:global_event_loop',
next reply other threads:[~2016-02-18 19:36 UTC|newest]
Thread overview: 195+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-18 19:35 Fabian Groffen [this message]
-- strict thread matches above, loose matches on Subject: below --
2024-02-25 9:40 [gentoo-commits] proj/portage:prefix commit in: / Fabian Groffen
2024-02-22 7:27 Fabian Groffen
2024-01-18 10:22 Fabian Groffen
2024-01-18 9:36 Fabian Groffen
2023-12-03 10:10 Fabian Groffen
2023-12-03 9:54 Fabian Groffen
2023-12-03 9:54 Fabian Groffen
2023-12-03 9:54 Fabian Groffen
2023-11-24 20:18 Fabian Groffen
2023-11-24 20:06 Fabian Groffen
2023-11-24 20:06 Fabian Groffen
2023-06-22 8:47 Fabian Groffen
2023-06-17 9:04 Fabian Groffen
2023-06-17 8:41 Fabian Groffen
2022-07-28 17:38 Fabian Groffen
2022-07-27 19:20 Fabian Groffen
2022-07-26 19:39 Fabian Groffen
2022-07-25 15:20 Fabian Groffen
2022-07-24 19:27 Fabian Groffen
2022-07-24 14:01 Fabian Groffen
2022-07-24 9:45 Fabian Groffen
2022-01-14 10:40 Fabian Groffen
2022-01-14 10:32 Fabian Groffen
2021-07-06 7:10 Fabian Groffen
2021-04-16 13:37 Fabian Groffen
2021-01-24 9:02 Fabian Groffen
2021-01-04 10:48 Fabian Groffen
2020-12-07 17:28 Fabian Groffen
2020-12-07 16:46 Fabian Groffen
2020-11-23 7:48 Fabian Groffen
2020-11-22 11:15 Fabian Groffen
2020-09-26 11:29 Fabian Groffen
2020-08-02 12:33 Fabian Groffen
2020-06-02 18:55 Fabian Groffen
2020-01-08 19:14 Fabian Groffen
2019-07-01 13:11 Fabian Groffen
2019-05-30 9:20 Fabian Groffen
2019-02-28 12:31 Fabian Groffen
2019-01-11 10:19 Fabian Groffen
2019-01-07 10:22 Fabian Groffen
2018-12-23 11:14 Fabian Groffen
2018-12-12 18:54 Fabian Groffen
2018-08-04 6:56 Fabian Groffen
2018-06-25 8:34 Fabian Groffen
2018-06-17 14:38 Fabian Groffen
2018-06-17 14:38 Fabian Groffen
2018-05-28 15:24 Fabian Groffen
2018-05-25 19:44 Fabian Groffen
2018-05-25 19:44 Fabian Groffen
2018-05-18 19:46 Fabian Groffen
2017-12-12 8:19 Fabian Groffen
2017-10-29 14:51 Fabian Groffen
2017-10-03 7:32 Fabian Groffen
2017-09-22 10:08 Fabian Groffen
2017-08-21 13:27 Fabian Groffen
2017-08-13 7:21 Fabian Groffen
2017-05-23 13:34 Fabian Groffen
2017-03-25 9:12 Fabian Groffen
2017-03-24 19:09 Fabian Groffen
2017-03-24 7:43 Fabian Groffen
2017-03-23 17:46 Fabian Groffen
2017-03-23 17:32 Fabian Groffen
2017-03-23 17:23 Fabian Groffen
2017-03-23 15:38 Fabian Groffen
2017-03-17 8:25 Fabian Groffen
2017-03-02 8:48 Fabian Groffen
2017-03-02 8:18 Fabian Groffen
2017-02-23 14:05 Fabian Groffen
2017-01-27 15:08 Fabian Groffen
2017-01-27 15:08 Fabian Groffen
2016-03-20 19:31 Fabian Groffen
2016-02-21 16:17 Fabian Groffen
2016-02-21 16:17 Fabian Groffen
2016-02-18 19:35 Fabian Groffen
2015-06-20 7:12 Fabian Groffen
2015-06-09 18:30 Fabian Groffen
2015-06-09 18:01 Fabian Groffen
2015-06-04 19:47 Fabian Groffen
2015-04-05 9:15 Fabian Groffen
2014-11-12 17:31 Fabian Groffen
2014-10-02 18:48 Fabian Groffen
2014-09-28 17:52 Fabian Groffen
2014-05-06 19:32 Fabian Groffen
2014-05-06 19:18 Fabian Groffen
2014-04-22 19:52 Fabian Groffen
2014-02-06 21:09 Fabian Groffen
2014-01-06 9:47 Fabian Groffen
2013-09-24 17:29 Fabian Groffen
2013-09-20 17:59 Fabian Groffen
2013-09-18 18:34 Fabian Groffen
2013-09-13 18:02 Fabian Groffen
2013-08-10 20:54 Fabian Groffen
2013-07-10 5:31 Fabian Groffen
2013-07-08 19:32 Fabian Groffen
2013-06-29 5:41 Fabian Groffen
2013-06-27 17:20 Fabian Groffen
2013-06-12 9:02 Fabian Groffen
2013-06-09 15:53 Fabian Groffen
2013-05-04 18:55 Fabian Groffen
2013-04-02 16:57 Fabian Groffen
2013-03-31 19:03 Fabian Groffen
2013-03-31 19:00 Fabian Groffen
2013-03-24 8:36 Fabian Groffen
2013-03-23 19:54 Fabian Groffen
2013-02-28 19:29 Fabian Groffen
2013-02-07 20:01 Fabian Groffen
2013-01-27 21:41 Fabian Groffen
2013-01-27 21:41 Fabian Groffen
2013-01-13 10:26 Fabian Groffen
2013-01-10 21:02 Fabian Groffen
2013-01-05 18:14 Fabian Groffen
2012-12-26 14:48 Fabian Groffen
2012-12-02 15:47 Fabian Groffen
2012-12-02 15:36 Fabian Groffen
2012-12-02 15:33 Fabian Groffen
2012-12-02 15:33 Fabian Groffen
2012-12-02 15:33 Fabian Groffen
2012-12-02 13:12 Fabian Groffen
2012-12-02 12:59 Fabian Groffen
2012-11-04 10:48 Fabian Groffen
2012-10-22 17:25 Fabian Groffen
2012-10-02 12:02 Fabian Groffen
2012-09-30 11:22 Fabian Groffen
2012-09-26 18:26 Fabian Groffen
2012-09-12 18:18 Fabian Groffen
2012-09-09 7:40 Fabian Groffen
2012-09-06 18:14 Fabian Groffen
2012-08-27 6:44 Fabian Groffen
2012-08-12 7:50 Fabian Groffen
2012-07-19 16:25 Fabian Groffen
2012-07-06 7:05 Fabian Groffen
2012-04-23 19:23 Fabian Groffen
2012-04-03 18:04 Fabian Groffen
2012-03-31 19:31 Fabian Groffen
2012-03-01 20:32 Fabian Groffen
2012-02-19 9:58 Fabian Groffen
2012-02-09 8:01 Fabian Groffen
2012-01-10 17:45 Fabian Groffen
2011-12-31 16:45 Fabian Groffen
2011-12-26 9:12 Fabian Groffen
2011-12-23 9:51 Fabian Groffen
2011-12-22 9:51 Fabian Groffen
2011-12-19 18:30 Fabian Groffen
2011-12-14 15:25 Fabian Groffen
2011-12-10 11:28 Fabian Groffen
2011-12-09 20:33 Fabian Groffen
2011-12-02 20:31 Fabian Groffen
2011-12-02 19:20 Fabian Groffen
2011-12-02 19:19 Fabian Groffen
2011-12-02 19:18 Fabian Groffen
2011-12-02 18:03 Fabian Groffen
2011-10-21 17:34 Fabian Groffen
2011-10-21 17:34 Fabian Groffen
2011-10-20 20:28 Fabian Groffen
2011-10-20 17:08 Fabian Groffen
2011-10-20 16:38 Fabian Groffen
2011-10-17 18:36 Fabian Groffen
2011-10-16 13:59 Fabian Groffen
2011-10-15 18:27 Fabian Groffen
2011-10-13 6:52 Fabian Groffen
2011-09-23 18:38 Fabian Groffen
2011-09-23 18:23 Fabian Groffen
2011-09-20 18:25 Fabian Groffen
2011-09-14 18:43 Fabian Groffen
2011-09-14 18:38 Fabian Groffen
2011-09-13 17:41 Fabian Groffen
2011-08-31 18:39 Fabian Groffen
2011-08-30 18:45 Fabian Groffen
2011-08-29 19:03 Fabian Groffen
2011-08-25 20:25 Fabian Groffen
2011-08-20 17:50 Fabian Groffen
2011-07-26 17:35 Fabian Groffen
2011-07-17 9:48 Fabian Groffen
2011-07-17 8:12 Fabian Groffen
2011-07-01 17:44 Fabian Groffen
2011-06-14 15:39 Fabian Groffen
2011-06-06 17:12 Fabian Groffen
2011-05-28 8:29 Fabian Groffen
2011-05-27 17:41 Fabian Groffen
2011-05-14 13:59 Fabian Groffen
2011-05-02 17:41 Fabian Groffen
2011-04-24 12:08 Fabian Groffen
2011-04-15 18:27 Fabian Groffen
2011-04-15 18:27 Fabian Groffen
2011-03-28 16:52 Fabian Groffen
2011-03-23 19:26 Fabian Groffen
2011-03-17 19:08 Fabian Groffen
2011-03-13 14:45 Fabian Groffen
2011-03-09 19:44 Fabian Groffen
2011-02-26 21:15 Fabian Groffen
2011-02-10 18:46 Fabian Groffen
2011-02-10 18:44 Fabian Groffen
2011-02-10 18:20 Fabian Groffen
2011-02-05 12:25 Fabian Groffen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1455824085.ac7a15e255d0c239fb52aeb3df160378518aa496.grobian@gentoo \
--to=grobian@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox