[TIC-CORE] support new api for exporting to specific format
[archive/20170607/tools/tic-core.git] / tic / dependency.py
1 #!/usr/bin/python
2 # Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
3 #
4 # Contact: 
5 # @author Chulwoo Shin <cw1.shin@samsung.com>
6
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
10 #
11 # http://www.apache.org/licenses/LICENSE-2.0
12 #
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.
18 #
19 # Contributors:
20 # - S-Core Co., Ltd
21
22 from lxml import etree
23 from tic.utils.error import TICError
24 import logging
25
26 def analyze_dependency(pkg_group):
27     
28     def dep_dfs(pkg_id):
29         logger = logging.getLogger(__name__)
30         if pkg_list[pkg_id].get('dependency') is not None:
31             return pkg_list[pkg_id].get('dependency')
32         
33         number[0] += 1
34         visited[pkg_id] = number[0]
35         min_num[pkg_id] = number[0]
36         stack.append(pkg_id)
37
38         dep_set = set([pkg_list[pkg_id]['name']])
39         
40         if pkg_list[pkg_id].get('requires'):
41             for req in pkg_list[pkg_id].get('requires'):
42                 req_id = req.get('id')
43                 if req_id is not None:
44                     if scc_list[req_id] > 0:
45                         dep_set.update(pkg_list[req_id].get('dependency'))
46                         continue
47                     
48                     if visited[req_id] == 0:
49                         dep_set.update(dep_dfs(req_id))
50                     
51                     min_num[pkg_id] = min(min_num[pkg_id], min_num[req_id])
52                 else:
53                     #TODO: package does not exist
54                     #logger.warning('%s does not exist in repo', req['name'])
55                     pass
56         
57         if min_num[pkg_id] == visited[pkg_id]:
58             # scc (string connected components)
59             make_scc(pkg_id, list(dep_set))
60         
61         return dep_set
62     
63     def make_scc(pkg_id, dep_list):
64         p_id = 0 
65         scc_num[0] += 1
66         # stack is not empty
67         while stack:
68             p_id = stack.pop()
69             scc_list[p_id] = scc_num[0]
70             pkg_list[p_id]['dependency'] = dep_list
71             if pkg_id == p_id:
72                 break
73     
74     def analyze():
75         for pkg_id in range(len(pkg_list)):
76             if visited[pkg_id] == 0:
77                 dep_dfs(pkg_id)
78     
79     #TODO: Exception handling
80     if not pkg_group:
81         return None
82     
83     # package install-dependency analysis
84     pkg_list = pkg_group.get('pkg_list')
85     number = [0]
86     scc_num = [0]
87     visited = [0]*len(pkg_list)
88     min_num = [0]*len(pkg_list)
89     scc_list = [0]*len(pkg_list)
90     stack = []
91     
92     return analyze()
93     
94 def get_installed_packages(recipe, repoinfo, pkg_group):
95     logger = logging.getLogger(__name__)
96     
97     if not recipe or not repoinfo:
98         return []
99     
100     default = recipe.get('Default')
101     config = recipe.get('Configurations')[0]
102     platform_name = config.get('Platform')
103     platform = recipe.get(platform_name)
104     
105     # check groups/extraPackages
106     group_set = set([])
107     extrapkg_set = set([])
108     for g in [default, platform, config]:
109         if g.has_key('Groups'):
110             group_set.update(g.get('Groups'))
111         if g.has_key('ExtraPackages'):
112             extrapkg_set.update(g.get('ExtraPackages'))
113     group_dict = dict.fromkeys(group_set)
114     
115     # parsing group.xml
116     try:
117         tree = etree.parse(repoinfo[0].get('comps'))
118         root = tree.getroot()
119     except etree.XMLSyntaxError as e:
120         raise TICError('primary.xml syntax error. %s', e)
121     
122     # Convert groups to packages
123     pkg_set = set([])
124     for elm in root.findall('group'):
125         group_name = elm.find('name').text
126         if group_dict.has_key(group_name):
127             pkglist = elm.find('packagelist')
128             plist = []
129             for pkgreq in pkglist.findall('packagereq'):                
130                 plist.append(pkgreq.text)
131             pkg_set.update(set(plist))
132     
133     # set up required package from group packages
134     pkg2id = pkg_group.get('pkg2id')
135     pkg_list = pkg_group.get('pkg_list')
136     for pkg in pkg_set:
137         pkg_id = pkg2id.get(pkg)
138         if pkg_id and pkg_list[pkg_id].get('dependency'):
139             extrapkg_set.update(set(pkg_list[pkg_id].get('dependency')))
140     
141     return list(extrapkg_set)