File tree Expand file tree Collapse file tree 2 files changed +32
-0
lines changed
Expand file tree Collapse file tree 2 files changed +32
-0
lines changed Original file line number Diff line number Diff line change @@ -65,6 +65,24 @@ def topological_sort(specs):
6565 edges = [(pkg , dep ) for pkg , dep in edges if dep != current_package ]
6666 # ...but keep blocking those that still depend on other stuff!
6767 leaves .extend (new_leaves - {pkg for pkg , _ in edges })
68+ # If we have any edges left, we have a cycle
69+ if edges :
70+ # Find a cycle by following dependencies
71+ cycle = []
72+ start = edges [0 ][0 ] # Start with any remaining package
73+ current = start
74+ while True :
75+ cycle .append (current )
76+ # Find what current depends on
77+ for pkg , dep in edges :
78+ if pkg == current :
79+ current = dep
80+ break
81+ if current in cycle : # We found a cycle
82+ cycle = cycle [cycle .index (current ):] # Trim to just the cycle
83+ dieOnError (True , "Dependency cycle detected: " + " -> " .join (cycle + [cycle [0 ]]))
84+ if current == start : # We've gone full circle
85+ break
6886
6987
7088def resolve_store_path (architecture , spec_hash ):
Original file line number Diff line number Diff line change 1212from alibuild_helpers .utilities import resolve_version
1313from alibuild_helpers .utilities import topological_sort
1414from alibuild_helpers .utilities import resolveFilename , resolveDefaultsFilename
15+ import alibuild_helpers
1516import os
1617import string
1718
@@ -344,5 +345,18 @@ def test_dont_drop_packages(self) -> None:
344345 self .assertEqual (frozenset (specs .keys ()),
345346 frozenset (topological_sort (specs )))
346347
348+ def test_cycle (self ) -> None :
349+ """Test that dependency cycles are detected and reported."""
350+ specs = {
351+ "A" : {"package" : "A" , "requires" : ["B" ]},
352+ "B" : {"package" : "B" , "requires" : ["C" ]},
353+ "C" : {"package" : "C" , "requires" : ["D" ]},
354+ "D" : {"package" : "D" , "requires" : ["A" ]}
355+ }
356+ with patch .object (alibuild_helpers .log , 'error' ) as mock_error :
357+ with self .assertRaises (SystemExit ) as cm :
358+ list (topological_sort (specs ))
359+ self .assertEqual (cm .exception .code , 1 )
360+ mock_error .assert_called_once_with ("%s" , "Dependency cycle detected: A -> B -> C -> D -> A" )
347361if __name__ == '__main__' :
348362 unittest .main ()
You can’t perform that action at this time.
0 commit comments