Add check of herds in metadata.xml
authorSebastian Pipping <sebastian@pipping.org>
Sat, 27 Feb 2010 02:37:45 +0000 (03:37 +0100)
committerZac Medico <zmedico@gmail.com>
Wed, 24 Mar 2010 01:51:17 +0000 (18:51 -0700)
bin/repoman
pym/repoman/herdbase.py [new file with mode: 0644]
pym/repoman/utilities.py

index 61a2c335917443eef23de213d26ff301cdad3bd7..144c193513f3a70f54010a33a22e03ed33726ee3 100755 (executable)
@@ -53,11 +53,13 @@ from portage import StringIO
 try:
        from repoman.checks import run_checks
        from repoman import utilities
+       from repoman.herdbase import make_herd_base
 except ImportError:
        from os import path as osp
        sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), 'pym'))
        from repoman.checks import run_checks
        from repoman import utilities
+       from repoman.herdbase import make_herd_base
 
 from _emerge.Package import Package
 from _emerge.RootConfig import RootConfig
@@ -981,6 +983,11 @@ check_ebuild_notadded = not \
 # Build a regex from thirdpartymirrors for the SRC_URI.mirror check.
 thirdpartymirrors = portage.flatten(list(repoman_settings.thirdpartymirrors().values()))
 
+try:
+       herd_base = make_herd_base(os.path.join(repoman_settings["PORTDIR"], "metadata/herds.xml"))
+except (EnvironmentError, ParseError) as e:
+       err(str(e))
+
 for x in scanlist:
        #ebuilds and digests added to cvs respectively.
        logging.info("checking package %s" % x)
@@ -1316,6 +1323,15 @@ for x in scanlist:
                                fails["metadata.bad"].append("%s/metadata.xml: %s" % (x, e))
                                del e
 
+                       # Run other metadata.xml checkers
+                       try:
+                               utilities.check_metadata(_metadata_xml, herd_base)
+                       except (EnvironmentError, ParseError, 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
diff --git a/pym/repoman/herdbase.py b/pym/repoman/herdbase.py
new file mode 100644 (file)
index 0000000..3734a2f
--- /dev/null
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+# repoman: Herd database analysis
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: $
+
+import xml.etree.ElementTree as ET
+from xml.parsers.expat import ExpatError
+from portage.exception import ParseError
+
+__all__ = [
+       "make_herd_base"
+]
+
+_SPECIAL_HERDS = set(('no-herd',))
+
+def _make_email(nick_name):
+       if not nick_name.endswith('@gentoo.org'):
+               nick_name = nick_name + '@gentoo.org'
+       return nick_name
+
+
+class HerdBase(object):
+       def __init__(self, herd_to_emails, all_emails):
+               self.herd_to_emails = herd_to_emails
+               self.all_emails = all_emails
+
+       def known_herd(self, herd_name):
+               if herd_name in _SPECIAL_HERDS:
+                       return True
+               return herd_name in self.herd_to_emails
+
+       def known_maintainer(self, nick_name):
+               return _make_email(nick_name) in self.all_emails
+
+       def maintainer_in_herd(self, nick_name, herd_name):
+               return _make_email(nick_name) in self.herd_to_emails[herd_name]
+
+
+def make_herd_base(filename):
+       herd_to_emails = dict()
+       all_emails = set()
+
+       try:
+               xml_tree = ET.parse(filename)
+       except ExpatError as e:
+               raise ParseError("metadata.xml: " + str(e))
+       
+       herds = xml_tree.findall('herd')
+       for h in herds:
+               _herd_name = h.find('name')
+               if _herd_name is None:
+                       continue
+               herd_name = _herd_name.text.strip()
+               del _herd_name
+
+               maintainers = h.findall('maintainer')
+               herd_emails = set()
+               for m in maintainers:
+                       _m_email = m.find('email')
+                       if _m_email is None:
+                               continue
+                       m_email = _m_email.text.strip()
+
+                       herd_emails.add(m_email)
+                       all_emails.add(m_email)
+
+               herd_to_emails[herd_name] = herd_emails
+
+       return HerdBase(herd_to_emails, all_emails)
+
+
+if __name__ == '__main__':
+       h = make_herd_base('/usr/portage/metadata/herds.xml')
+
+       assert(h.known_herd('sound'))
+       assert(not h.known_herd('media-sound'))
+
+       assert(h.known_maintainer('sping'))
+       assert(h.known_maintainer('sping@gentoo.org'))
+       assert(not h.known_maintainer('portage'))
+
+       assert(h.maintainer_in_herd('zmedico@gentoo.org', 'tools-portage'))
+       assert(not h.maintainer_in_herd('pva@gentoo.org', 'tools-portage'))
+
+       import pprint
+       pprint.pprint(h.herd_to_emails)
index d30552ed485a723df9d26b8335a344d2a8b87488..1efed76639383ef5332e446bbd9104fd32f36b53 100644 (file)
@@ -15,7 +15,9 @@ __all__ = [
        "get_commit_message_with_editor",
        "get_commit_message_with_stdin",
        "have_profile_dir",
-       "parse_metadata_use"
+       "parse_metadata_use",
+       "UnknownHerdsError",
+       "check_metadata"
 ]
 
 import codecs
@@ -30,6 +32,7 @@ except ImportError:
 from xml.dom import minidom
 from xml.dom import NotFoundErr
 from xml.parsers.expat import ExpatError
+import xml.etree.ElementTree as ET
 from portage import os
 from portage import _encodings
 from portage import _unicode_decode
@@ -149,6 +152,34 @@ def parse_metadata_use(metadata_xml_content, uselist=None):
        finally:
                metadatadom.unlink()
 
+
+class UnknownHerdsError(ValueError):
+       def __init__(self, herd_names):
+               _plural = len(herd_names) != 1
+               super(UnknownHerdsError, self).__init__(
+                       'Unknown %s %s' % (_plural and 'herds' or 'herd',
+                       ','.join('"%s"' % e for e in herd_names)))
+
+
+def check_metadata_herds(xml_tree, herd_base):
+       herd_nodes = xml_tree.findall('herd')
+       unknown_herds = [name for name in
+                       (e.text.strip() for e in herd_nodes)
+                       if not herd_base.known_herd(name)]
+
+       if unknown_herds:
+               raise UnknownHerdsError(unknown_herds)
+
+
+def check_metadata(metadata_xml_content, herd_base):
+       try:
+               xml_tree = ET.fromstring(metadata_xml_content)
+       except (ExpatError, ) as e:
+               raise exception.ParseError("metadata.xml: " + str(e))
+
+       check_metadata_herds(xml_tree, herd_base)
+
+
 def FindPackagesToScan(settings, startdir, reposplit):
        """ Try to find packages that need to be scanned