ebuild: fetch: Flatten conditionals in _get_fetch_resume_size
[portage.git] / bin / repoman
index 638bd37007c33aebf04db628400a9d568a2d58eb..1277f3644e64210b6e0ba3277589aee38e5d0ac1 100755 (executable)
@@ -1,5 +1,5 @@
-#!/usr/bin/python -O
-# Copyright 1999-2013 Gentoo Foundation
+#!/usr/bin/python -bbO
+# 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
@@ -56,6 +56,7 @@ except (ImportError, SystemError, RuntimeError, Exception):
 from portage import os
 from portage import _encodings
 from portage import _unicode_encode
+import repoman.checks
 from repoman.checks import run_checks
 from repoman import utilities
 from repoman.herdbase import make_herd_base
@@ -112,7 +113,7 @@ def err(txt):
        warn(txt)
        sys.exit(1)
 
-def exithandler(signum=None, frame=None):
+def exithandler(signum=None, _frame=None):
        logging.fatal("Interrupted; exiting...")
        if signum is None:
                sys.exit(1)
@@ -174,6 +175,11 @@ def ParseArgs(argv, qahelp):
                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')
 
@@ -212,6 +218,10 @@ def ParseArgs(argv, qahelp):
        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')
 
@@ -227,7 +237,7 @@ def ParseArgs(argv, qahelp):
                default_opts = portage.util.shlex_split(
                        repoman_settings.get("REPOMAN_DEFAULT_OPTS", ""))
                if default_opts:
-                       opts, args = parser.parse_args(default_opts + sys.argv[1:])
+                       opts, args = parser.parse_known_args(default_opts + sys.argv[1:])
 
        if opts.mode == 'help':
                parser.print_help(short=False)
@@ -324,6 +334,7 @@ qahelp = {
        "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",
@@ -392,12 +403,9 @@ qawarnings = set((
 "upstream.workaround",
 "LIVEVCS.stable",
 "LIVEVCS.unmasked",
+"IUSE.rubydeprecated",
 ))
 
-if portage.const._ENABLE_INHERIT_CHECK:
-       # This is experimental, so it's non-fatal.
-       qawarnings.add("inherit.missing")
-
 non_ascii_re = re.compile(r'[^\x00-\x7f]')
 
 missingvars = ["KEYWORDS", "LICENSE", "DESCRIPTION", "HOMEPAGE"]
@@ -416,16 +424,7 @@ valid_restrict = frozenset(["binchecks", "bindist",
        "fetch", "installsources", "mirror", "preserve-libs",
        "primaryuri", "splitdebug", "strip", "test", "userpriv"])
 
-live_eclasses = frozenset([
-       "bzr",
-       "cvs",
-       "darcs",
-       "git",
-       "git-2",
-       "mercurial",
-       "subversion",
-       "tla",
-])
+live_eclasses = portage.const.LIVE_ECLASSES
 
 suspect_rdepend = frozenset([
        "app-arch/cabextract",
@@ -476,6 +475,10 @@ suspect_virtual = {
        "dev-libs/libusb-compat":"virtual/libusb",
 }
 
+ruby_deprecated = frozenset([
+       "ruby_targets_ree18",
+])
+
 metadata_xml_encoding = 'UTF-8'
 metadata_xml_declaration = '<?xml version="1.0" encoding="%s"?>' % \
        (metadata_xml_encoding,)
@@ -493,6 +496,11 @@ 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).
@@ -1302,7 +1310,7 @@ if options.if_modified == "y":
                chain(mychanged, mynew, myremoved)))
 
 for x in effective_scanlist:
-       #ebuilds and digests added to cvs respectively.
+       # 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()
@@ -1396,9 +1404,9 @@ for x in effective_scanlist:
        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))
+                               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)
@@ -1741,7 +1749,7 @@ for x in effective_scanlist:
                                fails["metadata.bad"].append("%s/metadata.xml: %s" % (x, e))
                                del e
 
-               #Only carry out if in package directory or check forced
+               # 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.
@@ -1780,7 +1788,7 @@ for x in effective_scanlist:
                        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
+                       # ebuild not added to vcs
                        stats["ebuild.notadded"] += 1
                        fails["ebuild.notadded"].append(x + "/" + y + ".ebuild")
                myesplit = portage.pkgsplit(y)
@@ -2106,6 +2114,15 @@ for x in effective_scanlist:
                        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
@@ -2123,7 +2140,7 @@ for x in effective_scanlist:
                                        stats["LICENSE.deprecated"] += 1
                                        fails["LICENSE.deprecated"].append("%s: %s" % (relative_path, lic))
 
-               #keyword checks
+               # keyword checks
                myuse = myaux["KEYWORDS"].split()
                for mykey in myuse:
                        if mykey not in ("-*", "*", "~*"):
@@ -2139,7 +2156,7 @@ for x in effective_scanlist:
                                        stats["KEYWORDS.invalid"] += 1
                                        fails["KEYWORDS.invalid"].append(x + "/" + y + ".ebuild: %s (profile invalid)" % mykey)
 
-               #restrict checks
+               # restrict checks
                myrestrict = None
                try:
                        myrestrict = portage.dep.use_reduce(myaux["RESTRICT"], matchall=1, flat=True)
@@ -2155,7 +2172,7 @@ for x in effective_scanlist:
                                stats["RESTRICT.invalid"] += len(mybadrestrict)
                                for mybad in mybadrestrict:
                                        fails["RESTRICT.invalid"].append(x + "/" + y + ".ebuild: %s" % mybad)
-               #REQUIRED_USE check
+               # REQUIRED_USE check
                required_use = myaux["REQUIRED_USE"]
                if required_use:
                        if not eapi_has_required_use(eapi):
@@ -2221,132 +2238,133 @@ for x in effective_scanlist:
 
                for keyword, groups, prof in relevant_profiles:
 
-                               if prof.status not in ("stable", "dev") or \
-                                       prof.status == "dev" and not options.include_dev:
-                                       continue
+                       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", pkg.cp)
-                                       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) %s" % \
-                                                                       (relative_path, mytype, keyword,
-                                                                       prof, repr(atoms)))
-                                               else:
+                       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", pkg.cp)
+                               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) %s" % \
                                                                (relative_path, mytype, keyword,
                                                                prof, repr(atoms)))
+                                       else:
+                                               stats[mykey] += 1
+                                               fails[mykey].append("%s: %s: %s(%s) %s" % \
+                                                       (relative_path, mytype, keyword,
+                                                       prof, repr(atoms)))
 
                if not baddepsyntax and unknown_pkgs:
                        type_map = {}
@@ -2693,6 +2711,7 @@ else:
 
        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)
@@ -2748,6 +2767,8 @@ else:
                                # 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)...")
@@ -2977,6 +2998,11 @@ else:
                        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