Gentoo Archives: gentoo-portage-dev

From: "Michał Górny" <mgorny@g.o>
To: gentoo-portage-dev@l.g.o
Cc: "Michał Górny" <mgorny@g.o>
Subject: [gentoo-portage-dev] [PATCH 3/4] repoman: Use XML Schema for metadata.xml validation
Date: Sat, 16 Apr 2016 18:07:25
Message-Id: 1460830005-20475-4-git-send-email-mgorny@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH 0/4] GLEP 67 test cleanup & XML Schema for repoman by "Michał Górny"
1 ---
2 pym/repoman/_xml.py | 16 ++++++-------
3 pym/repoman/checks/ebuilds/pkgmetadata.py | 6 ++---
4 pym/repoman/metadata.py | 39 ++++++++++++++++---------------
5 pym/repoman/scanner.py | 8 +++----
6 4 files changed, 35 insertions(+), 34 deletions(-)
7
8 diff --git a/pym/repoman/_xml.py b/pym/repoman/_xml.py
9 index 2661f14..026cd3a 100644
10 --- a/pym/repoman/_xml.py
11 +++ b/pym/repoman/_xml.py
12 @@ -12,7 +12,7 @@ from portage import os
13 from portage.output import red
14 from portage.process import find_binary
15
16 -from repoman.metadata import fetch_metadata_dtd
17 +from repoman.metadata import fetch_metadata_xsd
18 from repoman._subprocess import repoman_getstatusoutput
19
20
21 @@ -53,12 +53,12 @@ class _MetadataTreeBuilder(xml.etree.ElementTree.TreeBuilder):
22
23 class XmlLint(object):
24
25 - def __init__(self, options, repoman_settings, metadata_dtd=None):
26 - self.metadata_dtd = (metadata_dtd or
27 - os.path.join(repoman_settings["DISTDIR"], 'metadata.dtd'))
28 + def __init__(self, options, repoman_settings, metadata_xsd=None):
29 + self.metadata_xsd = (metadata_xsd or
30 + os.path.join(repoman_settings["DISTDIR"], 'metadata.xsd'))
31 self.options = options
32 self.repoman_settings = repoman_settings
33 - self._is_capable = metadata_dtd is not None
34 + self._is_capable = metadata_xsd is not None
35 self.binary = None
36 self._check_capable()
37
38 @@ -70,7 +70,7 @@ class XmlLint(object):
39 print(red("!!! xmllint not found. Can't check metadata.xml.\n"))
40 self._is_capable = False
41 elif not self._is_capable:
42 - if not fetch_metadata_dtd(self.metadata_dtd, self.repoman_settings):
43 + if not fetch_metadata_xsd(self.metadata_xsd, self.repoman_settings):
44 sys.exit(1)
45 # this can be problematic if xmllint changes their output
46 self._is_capable = True
47 @@ -94,8 +94,8 @@ class XmlLint(object):
48 # xmlint can produce garbage output even on success, so only dump
49 # the ouput when it fails.
50 st, out = repoman_getstatusoutput(
51 - self.binary + " --nonet --noout --dtdvalid %s %s" % (
52 - portage._shell_quote(self.metadata_dtd),
53 + self.binary + " --nonet --noout --schema %s %s" % (
54 + portage._shell_quote(self.metadata_xsd),
55 portage._shell_quote(
56 os.path.join(checkdir, "metadata.xml"))))
57 if st != os.EX_OK:
58 diff --git a/pym/repoman/checks/ebuilds/pkgmetadata.py b/pym/repoman/checks/ebuilds/pkgmetadata.py
59 index 74fec69..0e583fd 100644
60 --- a/pym/repoman/checks/ebuilds/pkgmetadata.py
61 +++ b/pym/repoman/checks/ebuilds/pkgmetadata.py
62 @@ -40,20 +40,20 @@ from repoman._xml import _XMLParser, _MetadataTreeBuilder, XmlLint
63 class PkgMetadata(object):
64 '''Package metadata.xml checks'''
65
66 - def __init__(self, options, qatracker, repoman_settings, metadata_dtd=None):
67 + def __init__(self, options, qatracker, repoman_settings, metadata_xsd=None):
68 '''PkgMetadata init function
69
70 @param options: ArgumentParser.parse_known_args(argv[1:]) options
71 @param qatracker: QATracker instance
72 @param repoman_settings: settings instance
73 - @param metadata_dtd: path of metadata.dtd
74 + @param metadata_xsd: path of metadata.xsd
75 '''
76 self.options = options
77 self.qatracker = qatracker
78 self.repoman_settings = repoman_settings
79 self.musedict = {}
80 self.xmllint = XmlLint(self.options, self.repoman_settings,
81 - metadata_dtd=metadata_dtd)
82 + metadata_xsd=metadata_xsd)
83
84 def check(self, xpkg, checkdir, checkdirlist, repolevel):
85 '''Performs the checks on the metadata.xml for the package
86 diff --git a/pym/repoman/metadata.py b/pym/repoman/metadata.py
87 index f1fa53a..147f9d0 100644
88 --- a/pym/repoman/metadata.py
89 +++ b/pym/repoman/metadata.py
90 @@ -32,8 +32,9 @@ metadata_xml_declaration = '<?xml version="1.0" encoding="%s"?>' \
91 % (metadata_xml_encoding,)
92 metadata_doctype_name = 'pkgmetadata'
93 metadata_dtd_uri = 'http://www.gentoo.org/dtd/metadata.dtd'
94 +metadata_xsd_uri = 'http://www.gentoo.org/xml-schema/metadata.xsd'
95 # force refetch if the local copy creation time is older than this
96 -metadata_dtd_ctime_interval = 60 * 60 * 24 * 7 # 7 days
97 +metadata_xsd_ctime_interval = 60 * 60 * 24 * 7 # 7 days
98
99
100 def parse_metadata_use(xml_tree):
101 @@ -85,36 +86,36 @@ def parse_metadata_use(xml_tree):
102 return uselist
103
104
105 -def fetch_metadata_dtd(metadata_dtd, repoman_settings):
106 +def fetch_metadata_xsd(metadata_xsd, repoman_settings):
107 """
108 - Fetch metadata.dtd if it doesn't exist or the ctime is older than
109 - metadata_dtd_ctime_interval.
110 + Fetch metadata.xsd if it doesn't exist or the ctime is older than
111 + metadata_xsd_ctime_interval.
112 @rtype: bool
113 @return: True if successful, otherwise False
114 """
115
116 must_fetch = True
117 - metadata_dtd_st = None
118 + metadata_xsd_st = None
119 current_time = int(time.time())
120 try:
121 - metadata_dtd_st = os.stat(metadata_dtd)
122 + metadata_xsd_st = os.stat(metadata_xsd)
123 except EnvironmentError as e:
124 if e.errno not in (errno.ENOENT, errno.ESTALE):
125 raise
126 del e
127 else:
128 - # Trigger fetch if metadata.dtd mtime is old or clock is wrong.
129 - if abs(current_time - metadata_dtd_st.st_ctime) \
130 - < metadata_dtd_ctime_interval:
131 + # Trigger fetch if metadata.xsd mtime is old or clock is wrong.
132 + if abs(current_time - metadata_xsd_st.st_ctime) \
133 + < metadata_xsd_ctime_interval:
134 must_fetch = False
135
136 if must_fetch:
137 print()
138 print(
139 - "%s the local copy of metadata.dtd "
140 + "%s the local copy of metadata.xsd "
141 "needs to be refetched, doing that now" % green("***"))
142 print()
143 - parsed_url = urlparse(metadata_dtd_uri)
144 + parsed_url = urlparse(metadata_xsd_uri)
145 setting = 'FETCHCOMMAND_' + parsed_url.scheme.upper()
146 fcmd = repoman_settings.get(setting)
147 if not fcmd:
148 @@ -124,29 +125,29 @@ def fetch_metadata_dtd(metadata_dtd, repoman_settings):
149 return False
150
151 destdir = repoman_settings["DISTDIR"]
152 - fd, metadata_dtd_tmp = tempfile.mkstemp(
153 - prefix='metadata.dtd.', dir=destdir)
154 + fd, metadata_xsd_tmp = tempfile.mkstemp(
155 + prefix='metadata.xsd.', dir=destdir)
156 os.close(fd)
157
158 try:
159 if not portage.getbinpkg.file_get(
160 - metadata_dtd_uri, destdir, fcmd=fcmd,
161 - filename=os.path.basename(metadata_dtd_tmp)):
162 + metadata_xsd_uri, destdir, fcmd=fcmd,
163 + filename=os.path.basename(metadata_xsd_tmp)):
164 logging.error(
165 - "failed to fetch metadata.dtd from '%s'" % metadata_dtd_uri)
166 + "failed to fetch metadata.xsd from '%s'" % metadata_xsd_uri)
167 return False
168
169 try:
170 portage.util.apply_secpass_permissions(
171 - metadata_dtd_tmp,
172 + metadata_xsd_tmp,
173 gid=portage.data.portage_gid, mode=0o664, mask=0o2)
174 except portage.exception.PortageException:
175 pass
176
177 - os.rename(metadata_dtd_tmp, metadata_dtd)
178 + os.rename(metadata_xsd_tmp, metadata_xsd)
179 finally:
180 try:
181 - os.unlink(metadata_dtd_tmp)
182 + os.unlink(metadata_xsd_tmp)
183 except OSError:
184 pass
185
186 diff --git a/pym/repoman/scanner.py b/pym/repoman/scanner.py
187 index 36248cb..1384a12 100644
188 --- a/pym/repoman/scanner.py
189 +++ b/pym/repoman/scanner.py
190 @@ -82,11 +82,11 @@ class Scanner(object):
191 portage.util.stack_lists([self.categories], incremental=1))
192 self.categories = self.repo_settings.repoman_settings.categories
193
194 - metadata_dtd = None
195 + metadata_xsd = None
196 for path in reversed(self.repo_settings.repo_config.eclass_db.porttrees):
197 - path = os.path.join(path, 'metadata/dtd/metadata.dtd')
198 + path = os.path.join(path, 'metadata/xml-schema/metadata.xsd')
199 if os.path.exists(path):
200 - metadata_dtd = path
201 + metadata_xsd = path
202 break
203
204 self.portdb = repo_settings.portdb
205 @@ -216,7 +216,7 @@ class Scanner(object):
206 self.fetchcheck = FetchChecks(
207 self.qatracker, self.repo_settings, self.portdb, self.vcs_settings)
208 self.pkgmeta = PkgMetadata(self.options, self.qatracker,
209 - self.repo_settings.repoman_settings, metadata_dtd=metadata_dtd)
210 + self.repo_settings.repoman_settings, metadata_xsd=metadata_xsd)
211 self.thirdparty = ThirdPartyMirrors(self.repo_settings.repoman_settings, self.qatracker)
212 self.use_flag_checks = USEFlagChecks(self.qatracker, uselist)
213 self.keywordcheck = KeywordChecks(self.qatracker, self.options)
214 --
215 2.8.1