DetectCycles finds all cycles in the graph nolint:gocognit // TODO: refactor to reduce complexity
()
| 129 | // |
| 130 | //nolint:gocognit // TODO: refactor to reduce complexity |
| 131 | func (g *Graph) DetectCycles() [][]string { |
| 132 | var cycles [][]string |
| 133 | visited := make(map[string]bool) |
| 134 | recStack := make(map[string]bool) |
| 135 | path := []string{} |
| 136 | |
| 137 | var dfs func(taskID string) bool |
| 138 | dfs = func(taskID string) bool { |
| 139 | visited[taskID] = true |
| 140 | recStack[taskID] = true |
| 141 | path = append(path, taskID) |
| 142 | |
| 143 | for _, depID := range g.RevAdjacency[taskID] { |
| 144 | if !visited[depID] { |
| 145 | if dfs(depID) { |
| 146 | return true |
| 147 | } |
| 148 | } else if recStack[depID] { |
| 149 | // Found a cycle |
| 150 | cycleStart := -1 |
| 151 | for i, id := range path { |
| 152 | if id == depID { |
| 153 | cycleStart = i |
| 154 | break |
| 155 | } |
| 156 | } |
| 157 | if cycleStart != -1 { |
| 158 | cycle := make([]string, len(path)-cycleStart) |
| 159 | copy(cycle, path[cycleStart:]) |
| 160 | cycles = append(cycles, cycle) |
| 161 | } |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | path = path[:len(path)-1] |
| 166 | recStack[taskID] = false |
| 167 | return false |
| 168 | } |
| 169 | |
| 170 | for _, task := range g.Tasks { |
| 171 | if !visited[task.ID] { |
| 172 | dfs(task.ID) |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | return cycles |
| 177 | } |
| 178 | |
| 179 | // FilterTasks creates a subgraph with only the specified task IDs |
| 180 | func (g *Graph) FilterTasks(taskIDs map[string]bool) *Graph { |
no outgoing calls