2 # Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5 # @author Chulwoo Shin <cw1.shin@samsung.com>
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
11 # http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
22 from lxml import etree
23 from tic.utils.error import TICError
26 class RepodataParser(object):
28 def __init__(self, repodata_list):
29 self.repodata_list = repodata_list
31 def _xml_parse(self, pkg_group, tree, tag_dic):
32 meta_prefix = 'building-block'
33 meta_prefix_root = 'building-block-root-'
34 meta_prefix_sub1 = 'building-block-sub1-'
35 meta_pattern = re.compile(''.join(['^', meta_prefix, '-(?P<meta>root|sub1|sub2)-(?P<pkgname>.+)']), re.I)
36 meta_sub1_pattern = re.compile("(?P<root>.+)-(?P<sub1>.+)")
37 meta_sub2_pattern = re.compile("(?P<root>.+)-(?P<sub1>.+)-(?P<sub2>.+)")
41 pkg_list = pkg_group.get('pkg_list')
42 pkg2id = pkg_group.get('pkg2id')
43 provides2id = pkg_group.get('provides2id')
44 file2id = pkg_group.get('file2id')
45 meta_info = pkg_group.get('meta_info')
47 pkg_id = len(pkg_list)
49 for pkg in root.findall(tag_dic['package']):
51 pkg_name = pkg.findtext(tag_dic['name'])
53 # check whether a package is duplicated.
54 if pkg_name in pkg2id:
55 #TODO: Apply to policy of duplication
56 print('Package(', pkg_name, ') is duplicated. exclude the package')
59 pkg2id[pkg_name] = pkg_id
62 pkg_info['name'] = pkg_name
63 pkg_info['text'] = pkg_name
65 # Parsing meta-pkg using meta naming rule
66 meta_match = meta_pattern.search(pkg_info['name'])
67 if meta_match is not None:
68 #print(meta_match.group(0), ', ', meta_match.group('meta'), ', ', meta_match.group('pkgname'))
69 if meta_match.group('meta') == 'root':
70 meta_info['root'].append([pkg_info['name']])
71 pkg_info['meta'] = 'root'
72 elif meta_match.group('meta') == 'sub1':
73 sub1_match = meta_sub1_pattern.search(meta_match.group('pkgname'))
74 meta_info['sub1'].append([pkg_info['name'],
75 ''.join([meta_prefix_root, sub1_match.group('root')]),
77 pkg_info['meta'] = 'sub1'
78 elif meta_match.group('meta') == 'sub2':
79 sub2_match = meta_sub2_pattern.search(meta_match.group('pkgname'))
80 meta_info['sub2'].append([pkg_info['name'],
81 ''.join([meta_prefix_root, sub2_match.group('root')]),
82 ''.join([meta_prefix_sub1, sub2_match.group('root'),'-', sub2_match.group('sub1')])
84 pkg_info['meta'] = 'sub2'
85 pkg_info['nodes'] = []
87 pkg_info['arch'] = pkg.findtext(tag_dic['arch'])
88 pkg_info['version'] = pkg.find(tag_dic['version']).attrib['ver']
89 pkg_info['checksum'] = pkg.findtext(tag_dic['checksum'])
90 pkg_info['summary'] = pkg.findtext(tag_dic['summary'])
91 pkg_info['description'] = pkg.findtext(tag_dic['description'])
92 pkg_info['location'] = pkg.find(tag_dic['location']).attrib['href']
93 size_tag = pkg.find(tag_dic['size'])
94 pkg_info['size'] = size_tag.attrib['package']
95 pkg_info['installed'] = size_tag.attrib['installed']
97 format_tag = pkg.find(tag_dic['format'])
98 if(format_tag is not None):
99 requires_tag = format_tag.find(tag_dic['requires'])
100 if requires_tag is not None:
102 for rpm in requires_tag:
104 req_rpm['name'] = rpm.attrib['name']
105 if 'ver' in rpm.attrib:
106 req_rpm['ver'] = rpm.attrib['ver']
107 if 'flags' in rpm.attrib:
108 req_rpm['flags'] = rpm.attrib['flags']
109 dep_list.append(req_rpm)
110 pkg_info['requires'] = dep_list;
111 provides_tag = format_tag.find(tag_dic['provides'])
112 if provides_tag is not None:
114 for rpm in provides_tag:
116 provide['id'] = pkg_id
117 provide['name'] = rpm.attrib['name']
118 if 'ver' in rpm.attrib:
119 provide['ver'] = rpm.attrib['ver']
120 if 'flags' in rpm.attrib:
121 provide['flags'] = rpm.attrib['flags']
123 if rpm.attrib['name'] in provides2id:
124 provides2id[rpm.attrib['name']].append(provide)
126 provides2id[rpm.attrib['name']] = [provide]
127 dep_list.append(rpm.attrib['name'])
128 pkg_info['provides'] = dep_list;
129 conflicts_tag = format_tag.find(tag_dic['conflicts'])
130 if conflicts_tag is not None:
132 for rpm in conflicts_tag:
133 dep_list.append(rpm.attrib['name'])
134 pkg_info['conflicts'] = dep_list;
135 suggests_tag = format_tag.find(tag_dic['suggests'])
136 if suggests_tag is not None:
138 for rpm in suggests_tag:
139 dep_list.append(rpm.attrib['name'])
140 pkg_info['suggests'] = dep_list;
141 file_tag = format_tag.find(tag_dic['file'])
142 if file_tag is not None:
144 for file in format_tag.findall(tag_dic['file']):
147 f['name'] = file.text
148 if file.text in file2id:
149 file2id[file.text].append(f)
151 file2id[file.text] = [f]
152 dep_list.append(file.text)
153 pkg_info['file'] = dep_list;
154 pkg_list.append(pkg_info)
157 def _prepare_requires_id(self, pkg_group):
158 pkg_list = pkg_group.get('pkg_list')
159 pkg2id = pkg_group.get('pkg2id')
160 provides2id = pkg_group.get('provides2id')
161 file2id = pkg_group.get('file2id')
163 for pkg_id in range(len(pkg_list)):
164 requires = pkg_list[pkg_id].get('requires')
165 if requires is not None:
166 for req_info in requires:
167 req_name = req_info['name']
168 #TODO: Determine dependency search order
169 if req_name in provides2id:
170 #TODO: Select a package in provides (version?)
171 req_info['id'] = provides2id[req_name][0]['id']
172 elif req_name in pkg2id:
173 req_info['id'] = pkg2id[req_name]
174 elif req_name in file2id:
175 req_info['id'] = file2id[req_name][0]['id']
177 #TODO: Exception Check
178 # the dependent package does not exist.
179 #print('_req_parse::', req_name, ' does not exist')
182 def _get_tagname(self, tree):
183 root = tree.getroot()
185 # xmlns = re.sub('metadata$', '', root.tag)
186 tags['metadata'] = '{%s}metadata' % root.nsmap[None]
187 tags['package'] = '{%s}package' % root.nsmap[None]
188 tags['name'] = '{%s}name' % root.nsmap[None]
189 tags['arch'] = '{%s}arch' % root.nsmap[None]
190 tags['version'] = '{%s}version' % root.nsmap[None]
191 tags['checksum'] = '{%s}checksum' % root.nsmap[None]
192 tags['summary'] = '{%s}summary' % root.nsmap[None]
193 tags['description'] = '{%s}description' % root.nsmap[None]
194 tags['location'] = '{%s}location' % root.nsmap[None]
195 tags['size'] = '{%s}size' % root.nsmap[None]
196 tags['format'] = '{%s}format' % root.nsmap[None]
197 tags['requires'] = '{%s}requires' % root.nsmap['rpm']
198 tags['provides'] = '{%s}provides' % root.nsmap['rpm']
199 tags['conflicts'] = '{%s}conflicts' % root.nsmap['rpm']
200 tags['suggests'] = '{%s}suggests' % root.nsmap['rpm']
201 tags['file'] = '{%s}file' % root.nsmap[None]
205 if not self.repodata_list:
208 #TODO: repo URL validation
212 for repodata in self.repodata_list:
213 tree = etree.parse(repodata['primary'])
214 tree_list.append(tree)
215 except etree.XMLSyntaxError as e:
216 raise TICError('primary.xml syntax error.')
218 tag_dic = self._get_tagname(tree_list[0])
220 pkg_group = dict(pkg_list=[],
224 meta_info=dict(root=[],sub1=[],sub2=[]))
226 # parses the repodata (primary.xml)
227 for tree in tree_list:
228 self._xml_parse(pkg_group, tree, tag_dic)
230 # set the requires id
231 self._prepare_requires_id(pkg_group)