App: Remove duplicate from dependency graph #77
1 changed files with 30 additions and 33 deletions
|
|
@ -232,7 +232,6 @@ class App(Base):
|
||||||
for project in projects:
|
for project in projects:
|
||||||
if project in graph:
|
if project in graph:
|
||||||
continue
|
continue
|
||||||
for section in sections:
|
|
||||||
deps = self.get_project_refs(
|
deps = self.get_project_refs(
|
||||||
[project],
|
[project],
|
||||||
['pkg.requires.jw'],
|
['pkg.requires.jw'],
|
||||||
|
|
@ -259,45 +258,43 @@ class App(Base):
|
||||||
project: str,
|
project: str,
|
||||||
graph: Graph,
|
graph: Graph,
|
||||||
unvisited: list[str],
|
unvisited: list[str],
|
||||||
temp: set[str],
|
stack: list[str],
|
||||||
path: list[str],
|
) -> list[str] | None:
|
||||||
) -> str | None:
|
if project in stack:
|
||||||
if project in temp:
|
|
||||||
log(DEBUG, 'found circular dependency at project', project)
|
log(DEBUG, 'found circular dependency at project', project)
|
||||||
return project
|
idx = stack.index(project)
|
||||||
|
return stack[idx:] + [project]
|
||||||
if project not in unvisited:
|
if project not in unvisited:
|
||||||
return None
|
return None
|
||||||
temp.add(project)
|
stack.append(project)
|
||||||
if project in graph:
|
if project in graph:
|
||||||
for dep in graph[project]:
|
for dep in graph[project]:
|
||||||
last = self.__find_circular_deps_recursive(
|
cycle = self.__find_circular_deps_recursive(
|
||||||
dep, graph, unvisited, temp, path
|
dep, graph, unvisited, stack
|
||||||
)
|
)
|
||||||
if last is not None:
|
if cycle is not None:
|
||||||
path.insert(0, dep)
|
return cycle
|
||||||
return last
|
|
||||||
unvisited.remove(project)
|
unvisited.remove(project)
|
||||||
temp.remove(project)
|
stack.pop()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def __find_circular_deps(self, projects: list[str],
|
def __find_circular_deps(self, projects: list[str],
|
||||||
flavours: list[str]) -> list[str]:
|
flavours: list[str]) -> list[str]:
|
||||||
graph: Graph = {}
|
graph: Graph = {}
|
||||||
ret: list[str] = []
|
|
||||||
self.__read_dep_graph(projects, flavours, graph)
|
self.__read_dep_graph(projects, flavours, graph)
|
||||||
unvisited = list(graph.keys())
|
unvisited = list(graph.keys())
|
||||||
temp: set[str] = set()
|
|
||||||
flipped = self.__flip_dep_graph(graph)
|
flipped = self.__flip_dep_graph(graph)
|
||||||
while unvisited:
|
while unvisited:
|
||||||
project = unvisited[0]
|
project = unvisited[0]
|
||||||
log(DEBUG, 'Checking circular dependency of', project)
|
log(DEBUG, 'Checking circular dependency of', project)
|
||||||
last = self.__find_circular_deps_recursive(
|
cycle = self.__find_circular_deps_recursive(project, flipped, unvisited, [])
|
||||||
project, flipped, unvisited, temp, ret
|
if cycle is not None:
|
||||||
)
|
# An edge a -> b in the flipped graph means that b
|
||||||
if last is not None:
|
# depends on a, so reverse to report the cycle in the
|
||||||
log(DEBUG, f'Found circular dependency below {project}, last is {last}')
|
# original direction
|
||||||
ret.append(last)
|
cycle = list(reversed(cycle))
|
||||||
return ret
|
log(DEBUG, f'Found circular dependency: {" -> ".join(cycle)}')
|
||||||
|
return cycle
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def __init__(self, distro: Distro | None = None) -> None:
|
def __init__(self, distro: Distro | None = None) -> None:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue