Skip to content

Commit fbd007a

Browse files
dependency graph may be cyclic
Signed-off-by: Akash Kumar <meakash7902@gmail.com>
1 parent 5804939 commit fbd007a

File tree

1 file changed

+67
-9
lines changed

1 file changed

+67
-9
lines changed

pkg/client/client.go

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,13 +1194,6 @@ func (c *KpmClient) downloadDeps(deps pkg.Dependencies, lockDeps pkg.Dependencie
11941194

11951195
depGraph := graph.New(graph.StringHash, graph.Directed())
11961196

1197-
for _, d := range newDeps.Deps {
1198-
err := depGraph.AddVertex(fmt.Sprintf("%s@%s", d.Name, d.Version))
1199-
if err != nil {
1200-
return nil, nil, err
1201-
}
1202-
}
1203-
12041197
// Recursively download the dependencies of the new dependencies.
12051198
for _, d := range newDeps.Deps {
12061199
// Load kcl.mod file of the new downloaded dependencies.
@@ -1223,20 +1216,27 @@ func (c *KpmClient) downloadDeps(deps pkg.Dependencies, lockDeps pkg.Dependencie
12231216
}
12241217

12251218
source := fmt.Sprintf("%s@%s", d.Name, d.Version)
1219+
err = depGraph.AddVertex(source)
1220+
if err != nil {
1221+
if err != graph.ErrVertexAlreadyExists {
1222+
return nil, nil, err
1223+
}
1224+
}
1225+
12261226
sourcesOfNestedDepGraph, err := FindSource(nestedDepGraph)
12271227
if err != nil {
12281228
return nil, nil, err
12291229
}
12301230

1231-
depGraph, err = graph.Union(depGraph, nestedDepGraph)
1231+
depGraph, err = Union(depGraph, nestedDepGraph)
12321232
if err != nil {
12331233
return nil, nil, err
12341234
}
12351235

12361236
// make an edge between the source of all nested dep graph and main dep graph
12371237
for _, sourceOfNestedDepGraph := range sourcesOfNestedDepGraph {
12381238
err = depGraph.AddEdge(source, sourceOfNestedDepGraph)
1239-
if err != nil {
1239+
if err != nil && err != graph.ErrEdgeAlreadyExists {
12401240
return nil, nil, err
12411241
}
12421242
}
@@ -1341,3 +1341,61 @@ func FindSource[K comparable, T any](g graph.Graph[K, T]) ([]K, error) {
13411341
}
13421342
return sources, nil
13431343
}
1344+
1345+
// Union combines two given graphs into a new graph. The vertex hashes in both
1346+
// graphs are expected to be unique. The two input graphs will remain unchanged.
1347+
//
1348+
// Both graphs should be either directed or undirected. All traits for the new
1349+
// graph will be derived from g.
1350+
//
1351+
// If the same vertex happens to be in both g and h, then an error will not be
1352+
// thrown as happens in original Union function and successful operation takes place.
1353+
func Union[K comparable, T any](g, h graph.Graph[K, T]) (graph.Graph[K, T], error) {
1354+
union, err := g.Clone()
1355+
if err != nil {
1356+
return union, fmt.Errorf("failed to clone g: %w", err)
1357+
}
1358+
1359+
adjacencyMap, err := h.AdjacencyMap()
1360+
if err != nil {
1361+
return union, fmt.Errorf("failed to get adjacency map: %w", err)
1362+
}
1363+
1364+
addedEdges := make(map[K]map[K]struct{})
1365+
1366+
for currentHash := range adjacencyMap {
1367+
vertex, err := h.Vertex(currentHash)
1368+
if err != nil {
1369+
return union, fmt.Errorf("failed to get vertex %v: %w", currentHash, err)
1370+
}
1371+
1372+
err = union.AddVertex(vertex)
1373+
if err != nil && err != graph.ErrVertexAlreadyExists {
1374+
return union, fmt.Errorf("failed to add vertex %v: %w", currentHash, err)
1375+
}
1376+
}
1377+
1378+
for _, adjacencies := range adjacencyMap {
1379+
for _, edge := range adjacencies {
1380+
if _, sourceOK := addedEdges[edge.Source]; sourceOK {
1381+
if _, targetOK := addedEdges[edge.Source][edge.Target]; targetOK {
1382+
// If the edge addedEdges[source][target] exists, the edge
1383+
// has already been created and thus can be skipped here.
1384+
continue
1385+
}
1386+
}
1387+
1388+
err = union.AddEdge(edge.Source, edge.Target)
1389+
if err != nil && err != graph.ErrEdgeAlreadyExists {
1390+
return union, fmt.Errorf("failed to add edge (%v, %v): %w", edge.Source, edge.Target, err)
1391+
}
1392+
1393+
if _, ok := addedEdges[edge.Source]; !ok {
1394+
addedEdges[edge.Source] = make(map[K]struct{})
1395+
}
1396+
addedEdges[edge.Source][edge.Target] = struct{}{}
1397+
}
1398+
}
1399+
1400+
return union, nil
1401+
}

0 commit comments

Comments
 (0)