3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 from cmframework.apis.cmerror import CMError
18 class CMDependencySort(object):
19 def __init__(self, after=None, before=None):
28 self._convert_after_to_before(after)
29 self._find_all_entries()
31 self._sorted_entries = []
33 def _convert_after_to_before(self, after):
34 for entry, deps in after.iteritems():
35 self._entries.add(entry)
37 dep_before = self._before.get(dep, None)
40 self._before[dep] = dep_before
41 if entry not in dep_before:
42 dep_before.append(entry)
44 def _find_all_entries(self):
45 for entry, deps in self._before.iteritems():
46 self._entries.add(entry)
48 self._entries.add(dep)
52 return self._sorted_entries
54 def _sort_entries(self):
56 permanent_mark_list = []
57 for entry in self._entries:
58 if entry not in permanent_mark_list:
59 self._visit(entry, sorted_list, permanent_mark_list)
60 self._sorted_entries = sorted_list
62 def _visit(self, entry, sorted_list, permanent_mark_list, temporary_mark_list=None):
63 if not temporary_mark_list:
64 temporary_mark_list = []
66 if entry in permanent_mark_list:
69 if entry in temporary_mark_list:
70 raise CMError('Cycle detected in dependencies ({})'.format(entry))
72 temporary_mark_list.append(entry)
73 for dep in self._before.get(entry, []):
74 self._visit(dep, sorted_list, permanent_mark_list, temporary_mark_list)
75 permanent_mark_list.append(entry)
76 sorted_list.insert(0, entry)