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