forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 150
Expand file tree
/
Copy pathcmd_graph.py
More file actions
46 lines (36 loc) · 1.71 KB
/
Copy pathcmd_graph.py
File metadata and controls
46 lines (36 loc) · 1.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# SPDX-License-Identifier: GPL-2.0-only OR MIT
# Copyright (C) 2025 TNG Technology Consulting GmbH
from collections import deque
from dataclasses import dataclass, field
from typing import Iterator
from sbom.cmd_graph.cmd_graph_node import CmdGraphNode, CmdGraphNodeConfig
from sbom.path_utils import PathStr
@dataclass
class CmdGraph:
"""Directed acyclic graph of build dependencies primarily inferred from .cmd files produced during kernel builds"""
roots: list[CmdGraphNode] = field(default_factory=list)
@classmethod
def create(cls, root_paths: list[PathStr], config: CmdGraphNodeConfig) -> "CmdGraph":
"""
Recursively builds a dependency graph starting from `root_paths`.
Dependencies are mainly discovered by parsing the `.cmd` files.
Args:
root_paths (list[PathStr]): List of paths to root outputs relative to obj_tree
config (CmdGraphNodeConfig): Configuration options
Returns:
CmdGraph: A graph of all build dependencies for the given root files.
"""
node_cache: dict[PathStr, CmdGraphNode] = {}
root_nodes = [CmdGraphNode.create(root_path, config, node_cache) for root_path in root_paths]
return CmdGraph(root_nodes)
def __iter__(self) -> Iterator[CmdGraphNode]:
"""Traverse the graph in breadth-first order, yielding each unique node."""
visited: set[PathStr] = set()
node_stack: deque[CmdGraphNode] = deque(self.roots)
while len(node_stack) > 0:
node = node_stack.popleft()
if node.absolute_path in visited:
continue
visited.add(node.absolute_path)
node_stack.extend(node.children)
yield node