App: Return cycle path from find_circular_deps()

The __find_circular_deps() and find_circular_deps() methods now
return list[str] instead of bool. On a cycle, the path builds up the
dependency chain in __find_circular_deps_recursive(), and
__find_circular_deps() appends the closing project to complete the
cycle. An empty list means no cycle found.

CmdDep prints the cycle as 'a -> b -> c -> a' instead of a generic
message.

Assisted-by: unsloth/Qwen3.6-35B-A3B-GGUF:IQ4_NL and pi.dev
Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2026-06-30 11:26:52 +02:00
commit 24d67a5ec0
Signed by: Jan Lindemann
GPG key ID: 3750640C9E25DD61
2 changed files with 15 additions and 7 deletions

View file

@ -315,7 +315,8 @@ class App(Base):
temp.remove(project)
return None
def __find_circular_deps(self, projects: list[str], flavours: list[str]) -> bool:
def __find_circular_deps(self, projects: list[str],
flavours: list[str]) -> list[str]:
graph: Graph = {}
ret: list[str] = []
self.__read_dep_graph(projects, flavours, graph)
@ -330,8 +331,9 @@ class App(Base):
)
if last is not None:
log(DEBUG, f'Found circular dependency below {project}, last is {last}')
return True
return False
ret.append(last)
return ret
return []
def __init__(self, distro: Distro | None = None) -> None:
@ -627,5 +629,5 @@ class App(Base):
return ', '.join(intersection)
return None
def find_circular_deps(self, projects: list[str], flavours: list[str]) -> bool:
def find_circular_deps(self, projects: list[str], flavours: list[str]) -> list[str]:
return self.__find_circular_deps(projects, flavours)