2 # Copyright (c) 2016 Samsung Electronics Co., Ltd
4 # Licensed under the Flora License, Version 1.1 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://floralicense.org/license/
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
22 from operator import itemgetter
23 from tic.utils.rpmmisc import meetRequireVersion
26 def make_view_data(pkg_group):
27 logger = logging.getLogger(__name__)
29 def _select_provide_rpm(capability, require):
31 if require.get('ver') is not None:
32 for provide in capability:
33 ver_data = provide['data']
34 if not ver_data.get('ver'):
35 ver_data = pkg_dict.get(provide['name']).get('version')
36 if meetRequireVersion(require, ver_data):
37 provide_list.append(provide)
39 provide_list = capability
42 for provide in provide_list:
43 result.append(pkg_dict[provide['name']])
47 def set_meta_require(meta_info):
48 meta_nodes = meta_info.get('nodes')
50 for child_meta in meta_nodes:
51 set_meta_require(child_meta)
52 children.add(child_meta['metaname'])
55 pkg_info = pkg_dict[meta_info['metaname']]
56 for dep_tag in ['requires', 'recommends', 'suggests']:
57 if pkg_info.get(dep_tag):
58 for req in pkg_info.get(dep_tag):
60 if req['name'] in provides:
61 targets = _select_provide_rpm(provides[req['name']], req)
62 elif req['name'] in files:
63 for fname in files[req['name']]:
64 targets.append(pkg_dict.get(fname))
65 elif req['name'] in pkg_dict:
66 targets.append(pkg_dict.get(req['name']))
68 # the dependent package does not exist.
72 # The meta-pkg of the other group are excluded.
73 if pkg['name'] not in duplicate:
74 refer_count[pkg['id']] += 1
75 duplicate.add(pkg['name'])
78 if not pkg['name'] in children:
79 meta_nodes.append(make_linked_meta_node(pkg['name'], pkg['summary'], meta_info['category']))
81 meta_nodes.append(make_node(pkg, meta_info.get('category')))
82 # Added 'zz' to non meta-package because they are to be listed last
83 meta_nodes = sorted(meta_nodes, key = lambda k: 'aa'+k['metaname'] if 'metaname' in k else 'zz'+k['text'])
84 meta_info['nodes'] = meta_nodes
86 if meta_info['metaname'] =='building-blocks-sub2-Preset_iot-examples-3_RPI3_headless_devboard':
88 def make_node(pkg_info, category=None):
89 n = dict(text=pkg_info['name'], nodes=[])
90 if category: n['category'] = category
92 def make_meta_node(pkgname, viewtext):
93 return dict(text=viewtext, metaname=pkgname, nodes=[])
94 def make_linked_meta_node(pkgname, viewtext, cat):
95 return dict(text=' <i>'+viewtext+'</i>', metaname=pkgname, nodes=[], category=cat, tooltip="This is a link of a building block.")
96 def is_blank_ui_meta_node(pkgname):
97 return (pkgname[-8:-2] == '__UI__')
98 def handle_ui_meta_node(tag, node):
99 node['selectable'] = False
100 node['hideCheckbox'] = True
101 if tag == 'BR' or tag == 'br':
103 elif tag == 'HR' or tag == 'hr':
104 node['text'] = '<hr style="margin-bottom: 0px; margin-top: 0px; border-style: inset; border-width: 3px" />'
105 elif tag == 'SD' or tag == 'sd':
107 node['backColor'] = '#101010'
108 elif tag == 'SM' or tag == 'sm':
109 # Keep the summary text
110 node['text'] = node['text']
111 elif tag == 'HT' or tag == 'ht':
112 # Keep the summary (TODO: verify the usage of HTML tags.)
113 node['text'] = node['text'] # Do we need conversion?
117 def handle_description(node):
118 if 'metaname' in node:
119 name = node['metaname']
120 pkg_info = pkg_dict[name]
121 desc = pkg_info.get('description')
122 if desc[0:10] == '__KS_URL__':
123 logger.info("Processing "+name+" for its description: "+pkg_info.get('description'))
124 # Extract URL from __KS_URL__
125 ksURL = desc[11:].splitlines()[0].strip()
126 # Omit the first line with __KS_URL__ from showing.
127 pkg_info['description'] = desc[len(desc.splitlines(True)[0]):]
129 # Search for filename if directory is given
130 # e.g., Convert http://a.com/a/ to https://a.com/a/blahblah.ks
131 # Works for file-indexing html
132 if ksURL[-3:].lower() != ".ks":
135 if ksURL[-1:] != "/":
137 r = requests.get(ksURL)
138 if r.status_code == requests.codes.ok:
139 m = re.search('>([^<]*\\.ks)\\s*<', r.text)
142 if error == 0 and not m:
143 m = re.search('"([^"]*\\.ks)\\s*"', r.text)
145 m = re.search("'([^']*\\.ks)\\s*'", r.text)
149 node['icon'] = 'glyphicon glyphicon-remove-sign'
150 node['tooltip'] = 'Cannot find image base from' + ksURL
153 node['tooltip'] = 'Image base from '+ksURL
154 node['icon'] = 'glyphicon glyphicon-list-alt'
156 elif desc[0:10] == '__EXPAND__':
157 # Omit the first line with __EXPAND__ from showing.
158 pkg_info['description'] = desc[len(desc.splitlines(True)[0]):]
159 option = desc.splitlines()[0][10:].strip(': \t')
161 node['expandcondition'] = 'all'
163 node['expandcondition'] = option
166 # view_data for tree view on web-ui
168 # temporary dictionary for referencing meta
174 pkg_dict = pkg_group['pkg_dict']
175 provides = pkg_group['provides']
176 files = pkg_group['files']
177 refer_count = [0] * len(pkg_dict)
179 # sort meta-pkg by pkt_name in ascending order
180 meta_info = pkg_group.get('meta_info')
181 meta_info['root'] = sorted(meta_info['root'], key=itemgetter(0))
182 meta_info['sub1'] = sorted(meta_info['sub1'], key=itemgetter(0))
183 meta_info['sub2'] = sorted(meta_info['sub2'], key=itemgetter(0))
187 if meta_info.get('category'):
188 for category in meta_info['category']:
189 c_rpm = pkg_dict[category[0]]
190 if hasattr(c_rpm.get('suggests'), '__iter__'):
191 for suggest in c_rpm.get('suggests'):
192 category_dict[suggest['name']] = category[1]
194 logger.info(c_rpm.get('suggests'))
195 logger.info(c_rpm.get('name'))
199 for root in meta_info['root']:
200 root_node = make_meta_node(root[0], root[1])
201 view_ref[root[0]] = root_node
202 if root[0] in category_dict:
203 root_node['category'] = category_dict[root[0]]
204 if is_blank_ui_meta_node(root[0]):
206 sub1_node = handle_ui_meta_node(name[-2:], root_node)
207 root_node = handle_description(root_node)
208 view_data.append(root_node)
210 for sub1 in meta_info['sub1']:
211 sub1_node = make_meta_node(sub1[0], sub1[2])
212 view_ref[sub1[0]] = sub1_node
213 if is_blank_ui_meta_node(sub1[0]):
215 sub1_node = handle_ui_meta_node(name[-2:], sub1_node)
216 sub1_node = handle_description(sub1_node)
218 if sub1[1] in view_ref:
220 if 'category' in view_ref[sub1[1]] and view_ref[sub1[1]]['category']:
221 sub1_node['category'] = view_ref[sub1[1]]['category']
222 view_ref[sub1[1]]['nodes'].append(sub1_node)
224 # If root-meta does not exist, sub1 is added to top-level
225 view_data.append(sub1_node)
227 for sub2 in meta_info['sub2']:
228 sub2_node = make_meta_node(sub2[0], sub2[3])
229 view_ref[sub2[0]] = sub2_node
230 if is_blank_ui_meta_node(sub2[0]):
232 sub1_node = handle_ui_meta_node(name[-2:], sub2_node)
233 sub2_node = handle_description(sub2_node)
235 if sub2[2] in view_ref:
236 if 'category' in view_ref[sub2[2]] and view_ref[sub2[2]]['category']:
237 sub2_node['category'] = view_ref[sub2[2]]['category']
238 view_ref[sub2[2]]['nodes'].append(sub2_node)
240 elif sub2[1] in view_ref:
241 if view_ref[sub2[1]]['category']:
242 sub2_node['category'] = view_ref[sub2[1]]['category']
243 # If sub1-meta does not exist, sub2 is added to child of root-meta
244 view_ref[sub2[1]]['nodes'].append(sub2_node)
246 # If root-meta/sub1-meta does not exist, sub1 is added to top-level
247 view_data.append(sub2_node)
249 # configure meta dependency tree (requires)
250 for meta_pkg in view_data:
251 set_meta_require(meta_pkg)
253 #The remaining rpms are grouped into a MISC tree
255 misc_info['text'] = 'Advanced (individual packages)'
256 misc_info['nodes'] = []
257 for k, v in pkg_dict.iteritems():
258 # Add ALL non-block packages
259 if v['name'][0:15] != 'building-blocks':
260 misc_info['nodes'].append(make_node(v))
261 misc_info['nodes'] = sorted(misc_info['nodes'], key = lambda k: k['metaname'] if 'metaname' in k else k['text'])
263 view_data.append(misc_info)
264 logger.info('meta: %d, misc: %d', len(view_ref), len(misc_info['nodes']))