App: Remove duplicate from dependency graph #77

Merged
Jan Lindemann merged 2 commits from jan/fix/20260822-app-remove-duplicate-from-dependency-graph into master 2026-08-22 16:11:34 +02:00 AGit

This PR removes a duplicate from circular dependency detection and makes it faster. This fix affects a log message in CmdDep, but no functionality.

App.__read_dep_graph(): Remove redundant loop

__read_dep_graph() iterates over the given sections (flavours), but the loop body does not use the loop variable: it passes the entire sections list to get_project_refs() on every iteration, so the same lookup is repeated for each section, and the recursion into the found dependencies is re-triggered (and skipped) for each of them.

Remove the loop and do the lookup once per project.

App.__find_circular_deps(): Fix cycle path

__find_circular_deps_recursive() builds the cycle path by inserting each visited dependency at the front of the list on the way back up, and __find_circular_deps() appends the project where the cycle was detected at the end. The path therefore starts at the first child of the DFS root instead of at the project that closes the cycle, and the closing project appears twice: for a dependency cycle between projects A and B, find_circular_deps() reports "B -> A -> A" instead of "A -> B -> A".

Keep the DFS stack as an ordered list, and when a dependency is already on the stack, return the part of the stack from that dependency to the top, plus the dependency itself, which starts and ends at the same project. Reverse the result before returning, because an edge a -> b in the flipped graph means that b depends on a, so the cycle is reported in the original dependency direction.

This PR removes a duplicate from circular dependency detection and makes it faster. This fix affects a log message in CmdDep, but no functionality. #### App.__read_dep_graph(): Remove redundant loop __read_dep_graph() iterates over the given sections (flavours), but the loop body does not use the loop variable: it passes the entire sections list to get_project_refs() on every iteration, so the same lookup is repeated for each section, and the recursion into the found dependencies is re-triggered (and skipped) for each of them. Remove the loop and do the lookup once per project. #### App.__find_circular_deps(): Fix cycle path __find_circular_deps_recursive() builds the cycle path by inserting each visited dependency at the front of the list on the way back up, and __find_circular_deps() appends the project where the cycle was detected at the end. The path therefore starts at the first child of the DFS root instead of at the project that closes the cycle, and the closing project appears twice: for a dependency cycle between projects A and B, find_circular_deps() reports "B -> A -> A" instead of "A -> B -> A". Keep the DFS stack as an ordered list, and when a dependency is already on the stack, return the part of the stack from that dependency to the top, plus the dependency itself, which starts and ends at the same project. Reverse the result before returning, because an edge a -> b in the flipped graph means that b depends on a, so the cycle is reported in the original dependency direction.
__read_dep_graph() iterates over the given sections (flavours), but
the loop body does not use the loop variable: it passes the entire
sections list to get_project_refs() on every iteration, so the same
lookup is repeated for each section, and the recursion into the
found dependencies is re-triggered (and skipped) for each of them.

Remove the loop and do the lookup once per project.

Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v0.84.2
Signed-off-by: Jan Lindemann <jan@janware.com>
App.__find_circular_deps(): Fix cycle path
All checks were successful
CI / Packaging - Kali Linux (pull_request) Successful in 8m56s
CI / Packaging - OpenSUSE Tumbleweed (pull_request) Successful in 4m5s
CI / Packaging test (pull_request) Successful in 0s
bd7cfa4ff8
__find_circular_deps_recursive() builds the cycle path by inserting
each visited dependency at the front of the list on the way back up,
and __find_circular_deps() appends the project where the cycle was
detected at the end. The path therefore starts at the first child of
the DFS root instead of at the project that closes the cycle, and the
closing project appears twice: for a dependency cycle between projects
A and B, find_circular_deps() reports "B -> A -> A" instead of
"A -> B -> A".

Keep the DFS stack as an ordered list, and when a dependency is already
on the stack, return the part of the stack from that dependency to the
top, plus the dependency itself, which starts and ends at the same
project. Reverse the result before returning, because an edge
a -> b in the flipped graph means that b depends on a, so the cycle
is reported in the original dependency direction.

Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v0.84.2
Signed-off-by: Jan Lindemann <jan@janware.com>
Jan Lindemann scheduled this pull request to auto merge when all checks succeed 2026-08-22 15:53:12 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
janware/jw-pkg!77
No description provided.