From: "Sam James (sam_c)" <s...@cmpct.info>

Introduces new repos.conf/layout.conf variables:
* maintainer-nag (yes/no)
* maintainer-nag-url (URL to be given for volunteers to look at)

Bug: https://bugs.gentoo.org/711466
Closes: https://github.com/gentoo/portage/pull/529
Signed-off-by: Sam James (sam_c) <s...@cmpct.info>
Signed-off-by: Zac Medico <zmed...@gentoo.org>
---
 lib/_emerge/depgraph.py          | 48 ++++++++++++++++++++++++++++++++
 lib/portage/repository/config.py | 26 +++++++++++++++--
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index ec90e59df..216eec28e 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -53,6 +53,11 @@ from portage.util._eventloop.EventLoop import EventLoop
 from portage.util._eventloop.global_event_loop import global_event_loop
 from portage.versions import _pkg_str, catpkgsplit
 
+try:
+       from portage.xml.metadata import MetaDataXML
+except Exception:
+       MetaDataXML = None
+
 from _emerge.AtomArg import AtomArg
 from _emerge.Blocker import Blocker
 from _emerge.BlockerCache import BlockerCache
@@ -9163,6 +9168,49 @@ class depgraph(object):
                        show_mask_docs()
                        writemsg("\n", noiselevel=-1)
 
+               # Build a list of problematic packages
+               maintainer_nag_packages = []
+
+               for pkg in self._dynamic_config.digraph:
+                       if not isinstance(pkg, Package):
+                               continue
+
+                       if not pkg.type_name == 'ebuild':
+                               continue
+
+                       maintainer_nag = 
pkg.root_config.settings.repositories[pkg.repo].maintainer_nag
+                       maintainer_nag_url = 
pkg.root_config.settings.repositories[pkg.repo].maintainer_nag_url
+
+                       if not maintainer_nag:
+                               continue
+
+                       path = 
os.path.dirname(pkg.root_config.trees['porttree'].dbapi.findname(pkg.cpv, 
myrepo=pkg.repo))
+                       path = os.path.join(path, 'metadata.xml')
+
+                       if MetaDataXML is not None and os.path.isfile(path):
+                               try:
+                                       metadata_xml = MetaDataXML(path, None)
+                                       maintainer = 
metadata_xml.format_maintainer_string()
+                               except SyntaxError:
+                                       continue
+
+                               if not maintainer:
+                                       maintainer_nag_packages.append(pkg.cpv 
+ "::" + pkg.repo)
+
+               if maintainer_nag_packages:
+                       writemsg("\n" + colorize("WARN", "!!!") + \
+                                " The following packages have no maintainer. 
They are at greater risk of bugs." +
+                                "\n!!! You can help to keep it in tree and fix 
bugs (inc. possible security issues)")
+
+                       if maintainer_nag_url:
+                               writemsg("\n!!! Please see: " + 
maintainer_nag_url)
+
+                       writemsg("\n")
+                       for pkg in maintainer_nag_packages:
+                               writemsg("- " + pkg)
+                       writemsg("\n")
+
+
                for pargs, kwargs in 
self._dynamic_config._unsatisfied_deps_for_display:
                        self._show_unsatisfied_dep(*pargs, **kwargs)
 
diff --git a/lib/portage/repository/config.py b/lib/portage/repository/config.py
index 50ab18026..1309cef65 100644
--- a/lib/portage/repository/config.py
+++ b/lib/portage/repository/config.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2019 Gentoo Authors
+# Copyright 2010-2020 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 from __future__ import unicode_literals
@@ -96,6 +96,8 @@ class RepoConfig(object):
                'manifest_hashes',
                'manifest_required_hashes',
                'masters',
+               'maintainer_nag',
+               'maintainer_nag_url',
                'missing_repo_name',
                'module_specific_options',
                'name',
@@ -306,6 +308,8 @@ class RepoConfig(object):
                self.disable_manifest = False
                self.manifest_hashes = None
                self.manifest_required_hashes = None
+               self.maintainer_nag = repo_opts.get('maintainer-nag', 
'no').lower() in ('true', 'yes')
+               self.maintainer_nag_url = repo_opts.get('maintainer-nag-url')
                self.update_changelog = False
                self.cache_formats = None
                self.portage1_profiles = True
@@ -338,13 +342,23 @@ class RepoConfig(object):
                                self.name = layout_data['repo-name']
                                self.missing_repo_name = False
 
+                       # Override some repos.conf setting with layout.conf
                        for value in ('allow-missing-manifest',
                                'cache-formats',
-                               'create-manifest', 'disable-manifest', 
'manifest-hashes',
+                               'create-manifest', 'disable-manifest', 
'manifest-hashes', 'maintainer-nag', 'maintainer-nag-url',
                                'manifest-required-hashes', 'profile-formats', 
'properties-allowed', 'restrict-allowed',
                                'sign-commit', 'sign-manifest', 
'thin-manifest', 'update-changelog'):
                                setattr(self, value.lower().replace("-", "_"), 
layout_data[value])
 
+                       # Allow repos.conf override of layout.conf for these
+                       for value in ('maintainer-nag', 'maintainer-nag-url'):
+                               setting = repo_opts.get(value)
+                               if setting:
+                                       setattr(self, 
value.lower().replace("-", "_"), setting)
+
+                       self.maintainer_nag = (self.maintainer_nag.lower() in 
('true', 'yes')
+                               if isinstance(self.maintainer_nag, basestring) 
else self.maintainer_nag)
+
                        # If profile-formats specifies a default EAPI, then set
                        # self.eapi to that, otherwise set it to "0" as 
specified
                        # by PMS.
@@ -600,6 +614,8 @@ class RepoConfigLoader(object):
                                                        'clone_depth',
                                                        'eclass_overrides',
                                                        'force',
+                                                       'maintainer_nag',
+                                                       'maintainer_nag_url',
                                                        'masters',
                                                        
'module_specific_options',
                                                        'priority',
@@ -1045,6 +1061,7 @@ class RepoConfigLoader(object):
 
        def config_string(self):
                bool_keys = (
+                       "maintainer_nag",
                        "strict_misc_digests",
                        "sync_allow_hardlinks",
                        "sync_rcu",
@@ -1055,6 +1072,7 @@ class RepoConfigLoader(object):
                        "format",
                        "location",
                        "main_repo",
+                       "maintainer_nag_url",
                        "priority",
                        "sync_depth",
                        "sync_openpgp_keyserver",
@@ -1170,6 +1188,10 @@ def parse_layout_conf(repo_location, repo_name=None):
        data['create-manifest'] = manifest_policy != 'false'
        data['disable-manifest'] = manifest_policy == 'false'
 
+       data['maintainer-nag'] = layout_data.get('maintainer-nag', 
'no').lower() \
+               == 'yes'
+       data['maintainer-nag-url'] = layout_data.get('maintainer-nag-url', '')
+
        # for compatibility w/ PMS, fallback to pms; but also check if the
        # cache exists or not.
        cache_formats = layout_data.get('cache-formats', '').lower().split()
-- 
2.25.3


Reply via email to