Skip to content

Commit

Permalink
dependency graph may be cyclic
Browse files Browse the repository at this point in the history
Signed-off-by: Akash Kumar <meakash7902@gmail.com>
  • Loading branch information
AkashKumar7902 committed Feb 13, 2024
1 parent 5804939 commit 913d5df
Showing 1 changed file with 67 additions and 9 deletions.
76 changes: 67 additions & 9 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1194,13 +1194,6 @@ func (c *KpmClient) downloadDeps(deps pkg.Dependencies, lockDeps pkg.Dependencie

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

for _, d := range newDeps.Deps {
err := depGraph.AddVertex(fmt.Sprintf("%s@%s", d.Name, d.Version))
if err != nil {
return nil, nil, err
}
}

// Recursively download the dependencies of the new dependencies.
for _, d := range newDeps.Deps {
// Load kcl.mod file of the new downloaded dependencies.
Expand All @@ -1223,20 +1216,27 @@ func (c *KpmClient) downloadDeps(deps pkg.Dependencies, lockDeps pkg.Dependencie
}

source := fmt.Sprintf("%s@%s", d.Name, d.Version)
err = depGraph.AddVertex(source)
if err != nil {
if err != graph.ErrVertexAlreadyExists {
return nil, nil, err
}
}

sourcesOfNestedDepGraph, err := FindSource(nestedDepGraph)
if err != nil {
return nil, nil, err
}

depGraph, err = graph.Union(depGraph, nestedDepGraph)
depGraph, err = Union(depGraph, nestedDepGraph)
if err != nil {
return nil, nil, err
}

// make an edge between the source of all nested dep graph and main dep graph
for _, sourceOfNestedDepGraph := range sourcesOfNestedDepGraph {
err = depGraph.AddEdge(source, sourceOfNestedDepGraph)
if err != nil {
if err != nil && err != graph.ErrEdgeAlreadyExists {
return nil, nil, err
}
}
Expand Down Expand Up @@ -1341,3 +1341,61 @@ func FindSource[K comparable, T any](g graph.Graph[K, T]) ([]K, error) {
}
return sources, nil
}

// Union combines two given graphs into a new graph. The vertex hashes in both
// graphs are expected to be unique. The two input graphs will remain unchanged.
//
// Both graphs should be either directed or undirected. All traits for the new
// graph will be derived from g.
//
// If the same vertex happens to be in both g and h, then an error will not be
// thrown as happens in original Union function and successful operation takes place.
func Union[K comparable, T any](g, h graph.Graph[K, T]) (graph.Graph[K, T], error) {
union, err := g.Clone()
if err != nil {
return union, fmt.Errorf("failed to clone g: %w", err)
}

adjacencyMap, err := h.AdjacencyMap()
if err != nil {
return union, fmt.Errorf("failed to get adjacency map: %w", err)
}

addedEdges := make(map[K]map[K]struct{})

for currentHash := range adjacencyMap {
vertex, err := h.Vertex(currentHash)
if err != nil {
return union, fmt.Errorf("failed to get vertex %v: %w", currentHash, err)
}

err = union.AddVertex(vertex)
if err != nil && err != graph.ErrVertexAlreadyExists {
return union, fmt.Errorf("failed to add vertex %v: %w", currentHash, err)
}
}

for _, adjacencies := range adjacencyMap {
for _, edge := range adjacencies {
if _, sourceOK := addedEdges[edge.Source]; sourceOK {
if _, targetOK := addedEdges[edge.Source][edge.Target]; targetOK {
// If the edge addedEdges[source][target] exists, the edge
// has already been created and thus can be skipped here.
continue
}
}

err = union.AddEdge(edge.Source, edge.Target)
if err != nil {
return union, fmt.Errorf("failed to add edge (%v, %v): %w", edge.Source, edge.Target, err)
}

if _, ok := addedEdges[edge.Source]; !ok {
addedEdges[edge.Source] = make(map[K]struct{})
}
addedEdges[edge.Source][edge.Target] = struct{}{}
}
}

return union, nil
}

0 comments on commit 913d5df

Please sign in to comment.