@@ -50,32 +50,39 @@ export function detectAndReportWorkspaceCycles(
5050 * Finds one cycle in the workspace dependency graph, or returns `undefined` if there are none.
5151 *
5252 * Uses depth-first search with a "currently visiting" set for O(V + E) detection.
53+ * The `visiting` set doubles as the ordered path: ES6 Sets preserve insertion order,
54+ * so iterating it from the cycle-start node yields the cycle without a separate array.
5355 */
5456export function _findWorkspaceCycle (
5557 projects : ReadonlyArray < RushConfigurationProject >
5658) : ReadonlyArray < string > | undefined {
5759 // Nodes that have been fully explored (no cycles reachable from them)
5860 const visited : Set < RushConfigurationProject > = new Set ( ) ;
59- // Nodes currently on the DFS recursion stack
61+ // Nodes currently on the DFS recursion stack, in insertion order
6062 const visiting : Set < RushConfigurationProject > = new Set ( ) ;
61- // The current DFS path (used to extract the cycle path when one is found)
62- const path : RushConfigurationProject [ ] = [ ] ;
6363
6464 function dfs ( node : RushConfigurationProject ) : ReadonlyArray < string > | undefined {
6565 if ( visited . has ( node ) ) {
6666 return undefined ;
6767 }
6868 if ( visiting . has ( node ) ) {
69- // We've found a back-edge — extract the cycle from the current path
70- const cycleStartIndex : number = path . indexOf ( node ) ;
71- return [
72- ...path . slice ( cycleStartIndex ) . map ( ( p ) => p . packageName ) ,
73- node . packageName // append the closing node to make the cycle explicit
74- ] ;
69+ // Back-edge found — iterate `visiting` (insertion order) and collect from
70+ // the cycle-start node onward, then close the loop.
71+ const cycleNames : string [ ] = [ ] ;
72+ let found : boolean = false ;
73+ for ( const n of visiting ) {
74+ if ( n === node ) {
75+ found = true ;
76+ }
77+ if ( found ) {
78+ cycleNames . push ( n . packageName ) ;
79+ }
80+ }
81+ cycleNames . push ( node . packageName ) ; // close the cycle
82+ return cycleNames ;
7583 }
7684
7785 visiting . add ( node ) ;
78- path . push ( node ) ;
7986
8087 for ( const dep of node . dependencyProjects ) {
8188 const cycle : ReadonlyArray < string > | undefined = dfs ( dep ) ;
@@ -84,7 +91,6 @@ export function _findWorkspaceCycle(
8491 }
8592 }
8693
87- path . pop ( ) ;
8894 visiting . delete ( node ) ;
8995 visited . add ( node ) ;
9096 return undefined ;
0 commit comments