blob: 8b6737d6c5e13cf8fd0874a10f4f585ac8479628 [file] [log] [blame]
Bob Badour9ee7d032021-10-25 16:51:48 -07001// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package compliance
16
17// VisitNode is called for each root and for each walked dependency node by
18// WalkTopDown. When VisitNode returns true, WalkTopDown will proceed to walk
19// down the dependences of the node
20type VisitNode func(*LicenseGraph, *TargetNode, TargetEdgePath) bool
21
22// WalkTopDown does a top-down walk of `lg` calling `visit` and descending
23// into depenencies when `visit` returns true.
24func WalkTopDown(lg *LicenseGraph, visit VisitNode) {
25 path := NewTargetEdgePath(32)
26
27 // must be indexed for fast lookup
28 lg.indexForward()
29
30 var walk func(f string)
31 walk = func(f string) {
32 visitChildren := visit(lg, lg.targets[f], *path)
33 if !visitChildren {
34 return
35 }
36 for _, edge := range lg.index[f] {
37 path.Push(TargetEdge{lg, edge})
38 walk(edge.dependency)
39 path.Pop()
40 }
41 }
42
43 for _, r := range lg.rootFiles {
44 path.Clear()
45 walk(r)
46 }
47}
48
49// WalkResolutionsForCondition performs a top-down walk of the LicenseGraph
50// resolving all distributed works for condition `names`.
51func WalkResolutionsForCondition(lg *LicenseGraph, rs *ResolutionSet, names ConditionNames) *ResolutionSet {
52 shipped := ShippedNodes(lg)
53
54 // rmap maps 'attachesTo' targets to the `actsOn` targets and applicable conditions
55 //
56 // rmap is the resulting ResolutionSet
57 rmap := make(map[*TargetNode]actionSet)
58
59 WalkTopDown(lg, func(lg *LicenseGraph, tn *TargetNode, _ TargetEdgePath) bool {
60 if _, ok := rmap[tn]; ok {
61 return false
62 }
63 if !shipped.Contains(tn) {
64 return false
65 }
66 if as, ok := rs.resolutions[tn]; ok {
67 fas := as.byActsOn(shipped).byName(names)
68 if !fas.isEmpty() {
69 rmap[tn] = fas
70 }
71 }
72 return tn.IsContainer() // descend into containers
73 })
74
75 return &ResolutionSet{rmap}
76}