1 |
commit: 299745b29c06427fa0968b168f6fa60f91390be7 |
2 |
Author: Brian Dolbec <dolsen <AT> gentoo <DOT> org> |
3 |
AuthorDate: Mon Jun 2 03:35:06 2014 +0000 |
4 |
Commit: Brian Dolbec <brian.dolbec <AT> gmail <DOT> com> |
5 |
CommitDate: Mon Jun 2 03:35:06 2014 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=299745b2 |
7 |
|
8 |
Repoman metadata.xml: Create a new PkgMetadata class |
9 |
|
10 |
Move the metadata.xml checks to its own class in checks/ebuilds/pkgmetadata.py. |
11 |
Move the herd_base determination to checks/herds/herdbase.py in get_herd_base(). |
12 |
|
13 |
--- |
14 |
pym/repoman/checks/ebuilds/pkgmetadata.py | 170 ++++++++++++++++++++++++++++++ |
15 |
pym/repoman/checks/herds/herdbase.py | 16 ++- |
16 |
pym/repoman/main.py | 148 +------------------------- |
17 |
3 files changed, 190 insertions(+), 144 deletions(-) |
18 |
|
19 |
diff --git a/pym/repoman/checks/ebuilds/pkgmetadata.py b/pym/repoman/checks/ebuilds/pkgmetadata.py |
20 |
new file mode 100644 |
21 |
index 0000000..d40691d |
22 |
--- /dev/null |
23 |
+++ b/pym/repoman/checks/ebuilds/pkgmetadata.py |
24 |
@@ -0,0 +1,170 @@ |
25 |
+ |
26 |
+'''Package Metadata Checks operations''' |
27 |
+ |
28 |
+import sys |
29 |
+ |
30 |
+from itertools import chain |
31 |
+ |
32 |
+try: |
33 |
+ import xml.etree.ElementTree |
34 |
+ from xml.parsers.expat import ExpatError |
35 |
+except (SystemExit, KeyboardInterrupt): |
36 |
+ raise |
37 |
+except (ImportError, SystemError, RuntimeError, Exception): |
38 |
+ # broken or missing xml support |
39 |
+ # http://bugs.python.org/issue14988 |
40 |
+ msg = ["Please enable python's \"xml\" USE flag in order to use repoman."] |
41 |
+ from portage.output import EOutput |
42 |
+ out = EOutput() |
43 |
+ for line in msg: |
44 |
+ out.eerror(line) |
45 |
+ sys.exit(1) |
46 |
+ |
47 |
+import portage |
48 |
+from portage.exception import InvalidAtom |
49 |
+from portage import os |
50 |
+from portage import _encodings, _unicode_encode |
51 |
+from portage.dep import Atom |
52 |
+ |
53 |
+from repoman.metadata import (metadata_xml_encoding, metadata_doctype_name, |
54 |
+ metadata_dtd_uri, metadata_xml_declaration, parse_metadata_use) |
55 |
+from repoman.checks.herds.herdbase import get_herd_base |
56 |
+from repoman.checks.herds.metadata import check_metadata, UnknownHerdsError |
57 |
+from repoman._xml import _XMLParser, _MetadataTreeBuilder, XmlLint |
58 |
+ |
59 |
+ |
60 |
+class PkgMetadata(object): |
61 |
+ '''Package metadata.xml checks''' |
62 |
+ |
63 |
+ def __init__(self, options, qatracker, repolevel, repoman_settings): |
64 |
+ '''PkgMetadata init function |
65 |
+ |
66 |
+ @param options: ArgumentParser.parse_known_args(argv[1:]) options |
67 |
+ @param qatracker: QATracker instance |
68 |
+ @param repolevel: integer |
69 |
+ @param repoman_settings: settings instance |
70 |
+ ''' |
71 |
+ self.options = options |
72 |
+ self.qatracker = qatracker |
73 |
+ self.repolevel = repolevel |
74 |
+ self.repoman_settings = repoman_settings |
75 |
+ self.musedict = {} |
76 |
+ |
77 |
+ |
78 |
+ def check(self, xpkg, checkdir, checkdirlist): |
79 |
+ '''Performs the checks on the metadata.xml for the package |
80 |
+ |
81 |
+ @param xpkg: the pacakge being checked |
82 |
+ @param checkdir: string, directory path |
83 |
+ @param checkdirlist: list of checkdir's |
84 |
+ ''' |
85 |
+ |
86 |
+ self.musedict = {} |
87 |
+ # metadata.xml file check |
88 |
+ if "metadata.xml" not in checkdirlist: |
89 |
+ self.qatracker.add_error("metadata.missing", xpkg + "/metadata.xml") |
90 |
+ # metadata.xml parse check |
91 |
+ else: |
92 |
+ metadata_bad = False |
93 |
+ xml_info = {} |
94 |
+ xml_parser = _XMLParser(xml_info, target=_MetadataTreeBuilder()) |
95 |
+ |
96 |
+ # read metadata.xml into memory |
97 |
+ try: |
98 |
+ _metadata_xml = xml.etree.ElementTree.parse( |
99 |
+ _unicode_encode( |
100 |
+ os.path.join(checkdir, "metadata.xml"), |
101 |
+ encoding=_encodings['fs'], errors='strict'), |
102 |
+ parser=xml_parser) |
103 |
+ except (ExpatError, SyntaxError, EnvironmentError) as e: |
104 |
+ metadata_bad = True |
105 |
+ self.qatracker.add_error("metadata.bad", "%s/metadata.xml: %s" % (xpkg, e)) |
106 |
+ del e |
107 |
+ else: |
108 |
+ if not hasattr(xml_parser, 'parser') or \ |
109 |
+ sys.hexversion < 0x2070000 or \ |
110 |
+ (sys.hexversion > 0x3000000 and sys.hexversion < 0x3020000): |
111 |
+ # doctype is not parsed with python 2.6 or 3.1 |
112 |
+ pass |
113 |
+ else: |
114 |
+ if "XML_DECLARATION" not in xml_info: |
115 |
+ self.qatracker.add_error("metadata.bad", |
116 |
+ "%s/metadata.xml: " |
117 |
+ "xml declaration is missing on first line, " |
118 |
+ "should be '%s'" % (xpkg, metadata_xml_declaration)) |
119 |
+ else: |
120 |
+ xml_version, xml_encoding, xml_standalone = \ |
121 |
+ xml_info["XML_DECLARATION"] |
122 |
+ if xml_encoding is None or \ |
123 |
+ xml_encoding.upper() != metadata_xml_encoding: |
124 |
+ if xml_encoding is None: |
125 |
+ encoding_problem = "but it is undefined" |
126 |
+ else: |
127 |
+ encoding_problem = "not '%s'" % xml_encoding |
128 |
+ self.qatracker.add_error("metadata.bad", |
129 |
+ "%s/metadata.xml: " |
130 |
+ "xml declaration encoding should be '%s', %s" % |
131 |
+ (xpkg, metadata_xml_encoding, encoding_problem)) |
132 |
+ |
133 |
+ if "DOCTYPE" not in xml_info: |
134 |
+ metadata_bad = True |
135 |
+ self.qatracker.add_error("metadata.bad", |
136 |
+ "%s/metadata.xml: %s" % (xpkg, "DOCTYPE is missing")) |
137 |
+ else: |
138 |
+ doctype_name, doctype_system, doctype_pubid = \ |
139 |
+ xml_info["DOCTYPE"] |
140 |
+ if doctype_system != metadata_dtd_uri: |
141 |
+ if doctype_system is None: |
142 |
+ system_problem = "but it is undefined" |
143 |
+ else: |
144 |
+ system_problem = "not '%s'" % doctype_system |
145 |
+ self.qatracker.add_error("metadata.bad", |
146 |
+ "%s/metadata.xml: " |
147 |
+ "DOCTYPE: SYSTEM should refer to '%s', %s" % |
148 |
+ (xpkg, metadata_dtd_uri, system_problem)) |
149 |
+ |
150 |
+ if doctype_name != metadata_doctype_name: |
151 |
+ self.qatracker.add_error("metadata.bad", |
152 |
+ "%s/metadata.xml: " |
153 |
+ "DOCTYPE: name should be '%s', not '%s'" % |
154 |
+ (xpkg, metadata_doctype_name, doctype_name)) |
155 |
+ |
156 |
+ # load USE flags from metadata.xml |
157 |
+ try: |
158 |
+ self.musedict = parse_metadata_use(_metadata_xml) |
159 |
+ except portage.exception.ParseError as e: |
160 |
+ metadata_bad = True |
161 |
+ self.qatracker.add_error("metadata.bad", |
162 |
+ "%s/metadata.xml: %s" % (xpkg, e)) |
163 |
+ else: |
164 |
+ for atom in chain(*self.musedict.values()): |
165 |
+ if atom is None: |
166 |
+ continue |
167 |
+ try: |
168 |
+ atom = Atom(atom) |
169 |
+ except InvalidAtom as e: |
170 |
+ self.qatracker.add_error("metadata.bad", |
171 |
+ "%s/metadata.xml: Invalid atom: %s" % (xpkg, e)) |
172 |
+ else: |
173 |
+ if atom.cp != xpkg: |
174 |
+ self.qatracker.add_error("metadata.bad", |
175 |
+ "%s/metadata.xml: Atom contains " |
176 |
+ "unexpected cat/pn: %s" % (xpkg, atom)) |
177 |
+ |
178 |
+ # Run other metadata.xml checkers |
179 |
+ try: |
180 |
+ check_metadata(_metadata_xml, |
181 |
+ get_herd_base(self.repoman_settings)) |
182 |
+ except (UnknownHerdsError, ) as e: |
183 |
+ metadata_bad = True |
184 |
+ self.qatracker.add_error("metadata.bad", |
185 |
+ "%s/metadata.xml: %s" % (xpkg, e)) |
186 |
+ del e |
187 |
+ |
188 |
+ # Only carry out if in package directory or check forced |
189 |
+ if not metadata_bad: |
190 |
+ xmllint = XmlLint(self.options, self.repolevel, self.repoman_settings) |
191 |
+ if not xmllint.check(checkdir): |
192 |
+ self.qatracker.add_error("metadata.bad", xpkg + "/metadata.xml") |
193 |
+ del metadata_bad |
194 |
+ return |
195 |
|
196 |
diff --git a/pym/repoman/checks/herds/herdbase.py b/pym/repoman/checks/herds/herdbase.py |
197 |
index be555e5..b1ba671 100644 |
198 |
--- a/pym/repoman/checks/herds/herdbase.py |
199 |
+++ b/pym/repoman/checks/herds/herdbase.py |
200 |
@@ -22,9 +22,10 @@ except (ImportError, SystemError, RuntimeError, Exception): |
201 |
|
202 |
from portage import _encodings, _unicode_encode |
203 |
from portage.exception import FileNotFound, ParseError, PermissionDenied |
204 |
+from portage import os |
205 |
|
206 |
__all__ = [ |
207 |
- "make_herd_base" |
208 |
+ "make_herd_base", "get_herd_base" |
209 |
] |
210 |
|
211 |
|
212 |
@@ -102,6 +103,19 @@ def make_herd_base(filename): |
213 |
return HerdBase(herd_to_emails, all_emails) |
214 |
|
215 |
|
216 |
+def get_herd_base(repoman_settings): |
217 |
+ try: |
218 |
+ herd_base = make_herd_base( |
219 |
+ os.path.join(repoman_settings["PORTDIR"], "metadata/herds.xml")) |
220 |
+ except (EnvironmentError, ParseError, PermissionDenied) as e: |
221 |
+ err(str(e)) |
222 |
+ except FileNotFound: |
223 |
+ # TODO: Download as we do for metadata.dtd, but add a way to |
224 |
+ # disable for non-gentoo repoman users who may not have herds. |
225 |
+ herd_base = None |
226 |
+ return herd_base |
227 |
+ |
228 |
+ |
229 |
if __name__ == '__main__': |
230 |
h = make_herd_base('/usr/portage/metadata/herds.xml') |
231 |
|
232 |
|
233 |
diff --git a/pym/repoman/main.py b/pym/repoman/main.py |
234 |
index 1649c9f..d80cf59 100755 |
235 |
--- a/pym/repoman/main.py |
236 |
+++ b/pym/repoman/main.py |
237 |
@@ -25,20 +25,6 @@ import portage |
238 |
portage._internal_caller = True |
239 |
portage._disable_legacy_globals() |
240 |
|
241 |
-try: |
242 |
- import xml.etree.ElementTree |
243 |
- from xml.parsers.expat import ExpatError |
244 |
-except (SystemExit, KeyboardInterrupt): |
245 |
- raise |
246 |
-except (ImportError, SystemError, RuntimeError, Exception): |
247 |
- # broken or missing xml support |
248 |
- # http://bugs.python.org/issue14988 |
249 |
- msg = ["Please enable python's \"xml\" USE flag in order to use repoman."] |
250 |
- from portage.output import EOutput |
251 |
- out = EOutput() |
252 |
- for line in msg: |
253 |
- out.eerror(line) |
254 |
- sys.exit(1) |
255 |
|
256 |
from portage import os |
257 |
from portage import _encodings |
258 |
@@ -50,9 +36,7 @@ import portage.const |
259 |
import portage.repository.config |
260 |
from portage import cvstree, normalize_path |
261 |
from portage import util |
262 |
-from portage.exception import ( |
263 |
- FileNotFound, InvalidAtom, MissingParameter, ParseError, PermissionDenied) |
264 |
-from portage.dep import Atom |
265 |
+from portage.exception import MissingParameter |
266 |
from portage.process import find_binary, spawn |
267 |
from portage.output import ( |
268 |
bold, create_color_func, green, nocolor, red) |
269 |
@@ -66,11 +50,9 @@ from repoman.checks.ebuilds.checks import run_checks, checks_init |
270 |
from repoman.checks.ebuilds.isebuild import IsEbuild |
271 |
from repoman.checks.ebuilds.thirdpartymirrors import ThirdPartyMirrors |
272 |
from repoman.checks.ebuilds.manifests import Manifests |
273 |
-from repoman.checks.herds.herdbase import make_herd_base |
274 |
+from repoman.checks.ebuilds.pkgmetadata import PkgMetadata |
275 |
from repoman.ebuild import Ebuild |
276 |
from repoman.errors import err |
277 |
-from repoman.metadata import (metadata_xml_encoding, metadata_doctype_name, |
278 |
- metadata_dtd_uri, metadata_xml_declaration) |
279 |
from repoman.modules import commit |
280 |
from repoman.profile import check_profiles, dev_keywords, setup_profile |
281 |
from repoman.qa_data import (format_qa_output, format_qa_output_column, qahelp, |
282 |
@@ -84,7 +66,6 @@ from repoman import utilities |
283 |
from repoman.vcs.vcs import (git_supports_gpg_sign, vcs_files_to_cps, |
284 |
vcs_new_changed, VCSSettings) |
285 |
from repoman.vcs.vcsstatus import VCSStatus |
286 |
-from repoman._xml import _XMLParser, _MetadataTreeBuilder, XmlLint |
287 |
|
288 |
|
289 |
if sys.hexversion >= 0x3000000: |
290 |
@@ -214,7 +195,6 @@ portdb._aux_cache_keys.update( |
291 |
reposplit = myreporoot.split(os.path.sep) |
292 |
repolevel = len(reposplit) |
293 |
|
294 |
- |
295 |
################### |
296 |
|
297 |
if options.mode == 'commit': |
298 |
@@ -231,7 +211,6 @@ else: |
299 |
startdir = normalize_path(mydir) |
300 |
startdir = os.path.join(repo_settings.repodir, *startdir.split(os.sep)[-2 - repolevel + 3:]) |
301 |
|
302 |
- |
303 |
################### |
304 |
|
305 |
# get lists of valid keywords, licenses, and use |
306 |
@@ -295,16 +274,6 @@ if options.include_arches: |
307 |
check_ebuild_notadded = not \ |
308 |
(vcs_settings.vcs == "svn" and repolevel < 3 and options.mode != "commit") |
309 |
|
310 |
-try: |
311 |
- herd_base = make_herd_base( |
312 |
- os.path.join(repoman_settings["PORTDIR"], "metadata/herds.xml")) |
313 |
-except (EnvironmentError, ParseError, PermissionDenied) as e: |
314 |
- err(str(e)) |
315 |
-except FileNotFound: |
316 |
- # TODO: Download as we do for metadata.dtd, but add a way to |
317 |
- # disable for non-gentoo repoman users who may not have herds. |
318 |
- herd_base = None |
319 |
- |
320 |
effective_scanlist = scanlist |
321 |
if options.if_modified == "y": |
322 |
effective_scanlist = sorted(vcs_files_to_cps( |
323 |
@@ -490,118 +459,11 @@ for xpkg in effective_scanlist: |
324 |
|
325 |
if check_changelog and "ChangeLog" not in checkdirlist: |
326 |
qatracker.add_error("changelog.missing", xpkg + "/ChangeLog") |
327 |
- |
328 |
- musedict = {} |
329 |
- # metadata.xml file check |
330 |
- if "metadata.xml" not in checkdirlist: |
331 |
- qatracker.add_error("metadata.missing", xpkg + "/metadata.xml") |
332 |
- # metadata.xml parse check |
333 |
- else: |
334 |
- metadata_bad = False |
335 |
- xml_info = {} |
336 |
- xml_parser = _XMLParser(xml_info, target=_MetadataTreeBuilder()) |
337 |
- |
338 |
- # read metadata.xml into memory |
339 |
- try: |
340 |
- _metadata_xml = xml.etree.ElementTree.parse( |
341 |
- _unicode_encode( |
342 |
- os.path.join(checkdir, "metadata.xml"), |
343 |
- encoding=_encodings['fs'], errors='strict'), |
344 |
- parser=xml_parser) |
345 |
- except (ExpatError, SyntaxError, EnvironmentError) as e: |
346 |
- metadata_bad = True |
347 |
- qatracker.add_error("metadata.bad", "%s/metadata.xml: %s" % (xpkg, e)) |
348 |
- del e |
349 |
- else: |
350 |
- if not hasattr(xml_parser, 'parser') or \ |
351 |
- sys.hexversion < 0x2070000 or \ |
352 |
- (sys.hexversion > 0x3000000 and sys.hexversion < 0x3020000): |
353 |
- # doctype is not parsed with python 2.6 or 3.1 |
354 |
- pass |
355 |
- else: |
356 |
- if "XML_DECLARATION" not in xml_info: |
357 |
- qatracker.add_error("metadata.bad", |
358 |
- "%s/metadata.xml: " |
359 |
- "xml declaration is missing on first line, " |
360 |
- "should be '%s'" % (xpkg, metadata_xml_declaration)) |
361 |
- else: |
362 |
- xml_version, xml_encoding, xml_standalone = \ |
363 |
- xml_info["XML_DECLARATION"] |
364 |
- if xml_encoding is None or \ |
365 |
- xml_encoding.upper() != metadata_xml_encoding: |
366 |
- if xml_encoding is None: |
367 |
- encoding_problem = "but it is undefined" |
368 |
- else: |
369 |
- encoding_problem = "not '%s'" % xml_encoding |
370 |
- qatracker.add_error("metadata.bad", |
371 |
- "%s/metadata.xml: " |
372 |
- "xml declaration encoding should be '%s', %s" % |
373 |
- (xpkg, metadata_xml_encoding, encoding_problem)) |
374 |
- |
375 |
- if "DOCTYPE" not in xml_info: |
376 |
- metadata_bad = True |
377 |
- qatracker.add_error("metadata.bad", |
378 |
- "%s/metadata.xml: %s" % (xpkg, "DOCTYPE is missing")) |
379 |
- else: |
380 |
- doctype_name, doctype_system, doctype_pubid = \ |
381 |
- xml_info["DOCTYPE"] |
382 |
- if doctype_system != metadata_dtd_uri: |
383 |
- if doctype_system is None: |
384 |
- system_problem = "but it is undefined" |
385 |
- else: |
386 |
- system_problem = "not '%s'" % doctype_system |
387 |
- qatracker.add_error("metadata.bad", |
388 |
- "%s/metadata.xml: " |
389 |
- "DOCTYPE: SYSTEM should refer to '%s', %s" % |
390 |
- (xpkg, metadata_dtd_uri, system_problem)) |
391 |
- |
392 |
- if doctype_name != metadata_doctype_name: |
393 |
- qatracker.add_error("metadata.bad", |
394 |
- "%s/metadata.xml: " |
395 |
- "DOCTYPE: name should be '%s', not '%s'" % |
396 |
- (xpkg, metadata_doctype_name, doctype_name)) |
397 |
- |
398 |
- # load USE flags from metadata.xml |
399 |
- try: |
400 |
- musedict = utilities.parse_metadata_use(_metadata_xml) |
401 |
- except portage.exception.ParseError as e: |
402 |
- metadata_bad = True |
403 |
- qatracker.add_error("metadata.bad", |
404 |
- "%s/metadata.xml: %s" % (xpkg, e)) |
405 |
- else: |
406 |
- for atom in chain(*musedict.values()): |
407 |
- if atom is None: |
408 |
- continue |
409 |
- try: |
410 |
- atom = Atom(atom) |
411 |
- except InvalidAtom as e: |
412 |
- qatracker.add_error("metadata.bad", |
413 |
- "%s/metadata.xml: Invalid atom: %s" % (xpkg, e)) |
414 |
- else: |
415 |
- if atom.cp != xpkg: |
416 |
- qatracker.add_error("metadata.bad", |
417 |
- "%s/metadata.xml: Atom contains " |
418 |
- "unexpected cat/pn: %s" % (xpkg, atom)) |
419 |
- |
420 |
- # Run other metadata.xml checkers |
421 |
- try: |
422 |
- utilities.check_metadata(_metadata_xml, herd_base) |
423 |
- except (utilities.UnknownHerdsError, ) as e: |
424 |
- metadata_bad = True |
425 |
- qatracker.add_error("metadata.bad", |
426 |
- "%s/metadata.xml: %s" % (xpkg, e)) |
427 |
- del e |
428 |
- |
429 |
################# |
430 |
- # Only carry out if in package directory or check forced |
431 |
- if not metadata_bad: |
432 |
- xmllint = XmlLint(options, repolevel, repoman_settings) |
433 |
- if not xmllint.check(checkdir): |
434 |
- qatracker.add_error("metadata.bad", xpkg + "/metadata.xml") |
435 |
- |
436 |
+ pkgmeta = PkgMetadata(options, qatracker, repolevel, repoman_settings) |
437 |
+ pkgmeta.check(xpkg, checkdir, checkdirlist) |
438 |
+ muselist = frozenset(pkgmeta.musedict) |
439 |
################# |
440 |
- del metadata_bad |
441 |
- muselist = frozenset(musedict) |
442 |
|
443 |
changelog_path = os.path.join(checkdir_relative, "ChangeLog") |
444 |
changelog_modified = changelog_path in changed.changelogs |