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