1*9e94795aSAndroid Build Coastguard Worker// Copyright 2021 Google LLC 2*9e94795aSAndroid Build Coastguard Worker// 3*9e94795aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*9e94795aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*9e94795aSAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*9e94795aSAndroid Build Coastguard Worker// 7*9e94795aSAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*9e94795aSAndroid Build Coastguard Worker// 9*9e94795aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*9e94795aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*9e94795aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9e94795aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*9e94795aSAndroid Build Coastguard Worker// limitations under the License. 14*9e94795aSAndroid Build Coastguard Worker 15*9e94795aSAndroid Build Coastguard Workerpackage compliance 16*9e94795aSAndroid Build Coastguard Worker 17*9e94795aSAndroid Build Coastguard Workerimport ( 18*9e94795aSAndroid Build Coastguard Worker "fmt" 19*9e94795aSAndroid Build Coastguard Worker "sort" 20*9e94795aSAndroid Build Coastguard Worker "strings" 21*9e94795aSAndroid Build Coastguard Worker "sync" 22*9e94795aSAndroid Build Coastguard Worker) 23*9e94795aSAndroid Build Coastguard Worker 24*9e94795aSAndroid Build Coastguard Worker// LicenseGraph describes the immutable license metadata for a set of root 25*9e94795aSAndroid Build Coastguard Worker// targets and the transitive closure of their dependencies. 26*9e94795aSAndroid Build Coastguard Worker// 27*9e94795aSAndroid Build Coastguard Worker// Alternatively, a graph is a set of edges. In this case directed, annotated 28*9e94795aSAndroid Build Coastguard Worker// edges from targets to dependencies. 29*9e94795aSAndroid Build Coastguard Worker// 30*9e94795aSAndroid Build Coastguard Worker// A LicenseGraph provides the frame of reference for all of the other types 31*9e94795aSAndroid Build Coastguard Worker// defined here. It is possible to have multiple graphs, and to have targets, 32*9e94795aSAndroid Build Coastguard Worker// edges, and resolutions from multiple graphs. But it is an error to try to 33*9e94795aSAndroid Build Coastguard Worker// mix items from different graphs in the same operation. 34*9e94795aSAndroid Build Coastguard Worker// May panic if attempted. 35*9e94795aSAndroid Build Coastguard Worker// 36*9e94795aSAndroid Build Coastguard Worker// The compliance package assumes specific private implementations of each of 37*9e94795aSAndroid Build Coastguard Worker// these interfaces. May panic if attempts are made to combine different 38*9e94795aSAndroid Build Coastguard Worker// implementations of some interfaces with expected implementations of other 39*9e94795aSAndroid Build Coastguard Worker// interfaces here. 40*9e94795aSAndroid Build Coastguard Workertype LicenseGraph struct { 41*9e94795aSAndroid Build Coastguard Worker // rootFiles identifies the original set of files to read. (immutable) 42*9e94795aSAndroid Build Coastguard Worker // 43*9e94795aSAndroid Build Coastguard Worker // Defines the starting "top" for top-down walks. 44*9e94795aSAndroid Build Coastguard Worker // 45*9e94795aSAndroid Build Coastguard Worker // Alternatively, an instance of licenseGraphImp conceptually defines a scope within 46*9e94795aSAndroid Build Coastguard Worker // the universe of build graphs as a sub-graph rooted at rootFiles where all edges 47*9e94795aSAndroid Build Coastguard Worker // and targets for the instance are defined relative to and within that scope. For 48*9e94795aSAndroid Build Coastguard Worker // most analyses, the correct scope is to root the graph at all of the distributed 49*9e94795aSAndroid Build Coastguard Worker // artifacts. 50*9e94795aSAndroid Build Coastguard Worker rootFiles []string 51*9e94795aSAndroid Build Coastguard Worker 52*9e94795aSAndroid Build Coastguard Worker // edges lists the directed edges in the graph from target to dependency. (guarded by mu) 53*9e94795aSAndroid Build Coastguard Worker // 54*9e94795aSAndroid Build Coastguard Worker // Alternatively, the graph is the set of `edges`. 55*9e94795aSAndroid Build Coastguard Worker edges TargetEdgeList 56*9e94795aSAndroid Build Coastguard Worker 57*9e94795aSAndroid Build Coastguard Worker // targets identifies, indexes, and describes the entire set of target node files. 58*9e94795aSAndroid Build Coastguard Worker /// (guarded by mu) 59*9e94795aSAndroid Build Coastguard Worker targets map[string]*TargetNode 60*9e94795aSAndroid Build Coastguard Worker 61*9e94795aSAndroid Build Coastguard Worker // onceBottomUp makes sure the bottom-up resolve walk only happens one time. 62*9e94795aSAndroid Build Coastguard Worker onceBottomUp sync.Once 63*9e94795aSAndroid Build Coastguard Worker 64*9e94795aSAndroid Build Coastguard Worker // onceTopDown makes sure the top-down resolve walk only happens one time. 65*9e94795aSAndroid Build Coastguard Worker onceTopDown sync.Once 66*9e94795aSAndroid Build Coastguard Worker 67*9e94795aSAndroid Build Coastguard Worker // shippedNodes caches the results of a full walk of nodes identifying targets 68*9e94795aSAndroid Build Coastguard Worker // distributed either directly or as derivative works. (creation guarded by mu) 69*9e94795aSAndroid Build Coastguard Worker shippedNodes *TargetNodeSet 70*9e94795aSAndroid Build Coastguard Worker 71*9e94795aSAndroid Build Coastguard Worker // mu guards against concurrent update. 72*9e94795aSAndroid Build Coastguard Worker mu sync.Mutex 73*9e94795aSAndroid Build Coastguard Worker} 74*9e94795aSAndroid Build Coastguard Worker 75*9e94795aSAndroid Build Coastguard Worker// Edges returns the list of edges in the graph. (unordered) 76*9e94795aSAndroid Build Coastguard Workerfunc (lg *LicenseGraph) Edges() TargetEdgeList { 77*9e94795aSAndroid Build Coastguard Worker edges := make(TargetEdgeList, 0, len(lg.edges)) 78*9e94795aSAndroid Build Coastguard Worker edges = append(edges, lg.edges...) 79*9e94795aSAndroid Build Coastguard Worker return edges 80*9e94795aSAndroid Build Coastguard Worker} 81*9e94795aSAndroid Build Coastguard Worker 82*9e94795aSAndroid Build Coastguard Worker// Targets returns the list of target nodes in the graph. (unordered) 83*9e94795aSAndroid Build Coastguard Workerfunc (lg *LicenseGraph) Targets() TargetNodeList { 84*9e94795aSAndroid Build Coastguard Worker targets := make(TargetNodeList, 0, len(lg.targets)) 85*9e94795aSAndroid Build Coastguard Worker for _, target := range lg.targets { 86*9e94795aSAndroid Build Coastguard Worker targets = append(targets, target) 87*9e94795aSAndroid Build Coastguard Worker } 88*9e94795aSAndroid Build Coastguard Worker return targets 89*9e94795aSAndroid Build Coastguard Worker} 90*9e94795aSAndroid Build Coastguard Worker 91*9e94795aSAndroid Build Coastguard Worker// TargetNames returns the list of target node names in the graph. (unordered) 92*9e94795aSAndroid Build Coastguard Workerfunc (lg *LicenseGraph) TargetNames() []string { 93*9e94795aSAndroid Build Coastguard Worker targets := make([]string, 0, len(lg.targets)) 94*9e94795aSAndroid Build Coastguard Worker for target := range lg.targets { 95*9e94795aSAndroid Build Coastguard Worker targets = append(targets, target) 96*9e94795aSAndroid Build Coastguard Worker } 97*9e94795aSAndroid Build Coastguard Worker return targets 98*9e94795aSAndroid Build Coastguard Worker} 99*9e94795aSAndroid Build Coastguard Worker 100*9e94795aSAndroid Build Coastguard Worker// compliance-only LicenseGraph methods 101*9e94795aSAndroid Build Coastguard Worker 102*9e94795aSAndroid Build Coastguard Worker// newLicenseGraph constructs a new, empty instance of LicenseGraph. 103*9e94795aSAndroid Build Coastguard Workerfunc newLicenseGraph() *LicenseGraph { 104*9e94795aSAndroid Build Coastguard Worker return &LicenseGraph{ 105*9e94795aSAndroid Build Coastguard Worker rootFiles: []string{}, 106*9e94795aSAndroid Build Coastguard Worker targets: make(map[string]*TargetNode), 107*9e94795aSAndroid Build Coastguard Worker } 108*9e94795aSAndroid Build Coastguard Worker} 109*9e94795aSAndroid Build Coastguard Worker 110*9e94795aSAndroid Build Coastguard Worker// TargetEdge describes a directed, annotated edge from a target to a 111*9e94795aSAndroid Build Coastguard Worker// dependency. (immutable) 112*9e94795aSAndroid Build Coastguard Worker// 113*9e94795aSAndroid Build Coastguard Worker// A LicenseGraph, above, is a set of TargetEdges. 114*9e94795aSAndroid Build Coastguard Worker// 115*9e94795aSAndroid Build Coastguard Worker// i.e. `Target` depends on `Dependency` in the manner described by 116*9e94795aSAndroid Build Coastguard Worker// `Annotations`. 117*9e94795aSAndroid Build Coastguard Workertype TargetEdge struct { 118*9e94795aSAndroid Build Coastguard Worker // target and dependency identify the nodes connected by the edge. 119*9e94795aSAndroid Build Coastguard Worker target, dependency *TargetNode 120*9e94795aSAndroid Build Coastguard Worker 121*9e94795aSAndroid Build Coastguard Worker // annotations identifies the set of compliance-relevant annotations describing the edge. 122*9e94795aSAndroid Build Coastguard Worker annotations TargetEdgeAnnotations 123*9e94795aSAndroid Build Coastguard Worker} 124*9e94795aSAndroid Build Coastguard Worker 125*9e94795aSAndroid Build Coastguard Worker// Target identifies the target that depends on the dependency. 126*9e94795aSAndroid Build Coastguard Worker// 127*9e94795aSAndroid Build Coastguard Worker// Target needs Dependency to build. 128*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) Target() *TargetNode { 129*9e94795aSAndroid Build Coastguard Worker return e.target 130*9e94795aSAndroid Build Coastguard Worker} 131*9e94795aSAndroid Build Coastguard Worker 132*9e94795aSAndroid Build Coastguard Worker// Dependency identifies the target depended on by the target. 133*9e94795aSAndroid Build Coastguard Worker// 134*9e94795aSAndroid Build Coastguard Worker// Dependency builds without Target, but Target needs Dependency to build. 135*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) Dependency() *TargetNode { 136*9e94795aSAndroid Build Coastguard Worker return e.dependency 137*9e94795aSAndroid Build Coastguard Worker} 138*9e94795aSAndroid Build Coastguard Worker 139*9e94795aSAndroid Build Coastguard Worker// Annotations describes the type of edge by the set of annotations attached to 140*9e94795aSAndroid Build Coastguard Worker// it. 141*9e94795aSAndroid Build Coastguard Worker// 142*9e94795aSAndroid Build Coastguard Worker// Only annotations prescribed by policy have any meaning for licensing, and 143*9e94795aSAndroid Build Coastguard Worker// the meaning for licensing is likewise prescribed by policy. Other annotations 144*9e94795aSAndroid Build Coastguard Worker// are preserved and ignored by policy. 145*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) Annotations() TargetEdgeAnnotations { 146*9e94795aSAndroid Build Coastguard Worker return e.annotations 147*9e94795aSAndroid Build Coastguard Worker} 148*9e94795aSAndroid Build Coastguard Worker 149*9e94795aSAndroid Build Coastguard Worker// IsRuntimeDependency returns true for edges representing shared libraries 150*9e94795aSAndroid Build Coastguard Worker// linked dynamically at runtime. 151*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) IsRuntimeDependency() bool { 152*9e94795aSAndroid Build Coastguard Worker return edgeIsDynamicLink(e) 153*9e94795aSAndroid Build Coastguard Worker} 154*9e94795aSAndroid Build Coastguard Worker 155*9e94795aSAndroid Build Coastguard Worker// IsDerivation returns true for edges where the target is a derivative 156*9e94795aSAndroid Build Coastguard Worker// work of dependency. 157*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) IsDerivation() bool { 158*9e94795aSAndroid Build Coastguard Worker return edgeIsDerivation(e) 159*9e94795aSAndroid Build Coastguard Worker} 160*9e94795aSAndroid Build Coastguard Worker 161*9e94795aSAndroid Build Coastguard Worker// IsBuildTool returns true for edges where the target is built 162*9e94795aSAndroid Build Coastguard Worker// by dependency. 163*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) IsBuildTool() bool { 164*9e94795aSAndroid Build Coastguard Worker return !edgeIsDerivation(e) && !edgeIsDynamicLink(e) 165*9e94795aSAndroid Build Coastguard Worker} 166*9e94795aSAndroid Build Coastguard Worker 167*9e94795aSAndroid Build Coastguard Worker// String returns a human-readable string representation of the edge. 168*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) String() string { 169*9e94795aSAndroid Build Coastguard Worker return fmt.Sprintf("%s -[%s]> %s", e.target.name, strings.Join(e.annotations.AsList(), ", "), e.dependency.name) 170*9e94795aSAndroid Build Coastguard Worker} 171*9e94795aSAndroid Build Coastguard Worker 172*9e94795aSAndroid Build Coastguard Worker// TargetEdgeList orders lists of edges by target then dependency then annotations. 173*9e94795aSAndroid Build Coastguard Workertype TargetEdgeList []*TargetEdge 174*9e94795aSAndroid Build Coastguard Worker 175*9e94795aSAndroid Build Coastguard Worker// Len returns the count of the elmements in the list. 176*9e94795aSAndroid Build Coastguard Workerfunc (l TargetEdgeList) Len() int { return len(l) } 177*9e94795aSAndroid Build Coastguard Worker 178*9e94795aSAndroid Build Coastguard Worker// Swap rearranges 2 elements so that each occupies the other's former position. 179*9e94795aSAndroid Build Coastguard Workerfunc (l TargetEdgeList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 180*9e94795aSAndroid Build Coastguard Worker 181*9e94795aSAndroid Build Coastguard Worker// Less returns true when the `i`th element is lexicographically less than the `j`th. 182*9e94795aSAndroid Build Coastguard Workerfunc (l TargetEdgeList) Less(i, j int) bool { 183*9e94795aSAndroid Build Coastguard Worker namei := l[i].target.name 184*9e94795aSAndroid Build Coastguard Worker namej := l[j].target.name 185*9e94795aSAndroid Build Coastguard Worker if namei == namej { 186*9e94795aSAndroid Build Coastguard Worker namei = l[i].dependency.name 187*9e94795aSAndroid Build Coastguard Worker namej = l[j].dependency.name 188*9e94795aSAndroid Build Coastguard Worker } 189*9e94795aSAndroid Build Coastguard Worker if namei == namej { 190*9e94795aSAndroid Build Coastguard Worker return l[i].annotations.Compare(l[j].annotations) < 0 191*9e94795aSAndroid Build Coastguard Worker } 192*9e94795aSAndroid Build Coastguard Worker return namei < namej 193*9e94795aSAndroid Build Coastguard Worker} 194*9e94795aSAndroid Build Coastguard Worker 195*9e94795aSAndroid Build Coastguard Worker// TargetEdgePathSegment describes a single arc in a TargetPath associating the 196*9e94795aSAndroid Build Coastguard Worker// edge with a context `ctx` defined by whatever process is creating the path. 197*9e94795aSAndroid Build Coastguard Workertype TargetEdgePathSegment struct { 198*9e94795aSAndroid Build Coastguard Worker edge *TargetEdge 199*9e94795aSAndroid Build Coastguard Worker ctx interface{} 200*9e94795aSAndroid Build Coastguard Worker} 201*9e94795aSAndroid Build Coastguard Worker 202*9e94795aSAndroid Build Coastguard Worker// Target identifies the target that depends on the dependency. 203*9e94795aSAndroid Build Coastguard Worker// 204*9e94795aSAndroid Build Coastguard Worker// Target needs Dependency to build. 205*9e94795aSAndroid Build Coastguard Workerfunc (s TargetEdgePathSegment) Target() *TargetNode { 206*9e94795aSAndroid Build Coastguard Worker return s.edge.target 207*9e94795aSAndroid Build Coastguard Worker} 208*9e94795aSAndroid Build Coastguard Worker 209*9e94795aSAndroid Build Coastguard Worker// Dependency identifies the target depended on by the target. 210*9e94795aSAndroid Build Coastguard Worker// 211*9e94795aSAndroid Build Coastguard Worker// Dependency builds without Target, but Target needs Dependency to build. 212*9e94795aSAndroid Build Coastguard Workerfunc (s TargetEdgePathSegment) Dependency() *TargetNode { 213*9e94795aSAndroid Build Coastguard Worker return s.edge.dependency 214*9e94795aSAndroid Build Coastguard Worker} 215*9e94795aSAndroid Build Coastguard Worker 216*9e94795aSAndroid Build Coastguard Worker// Edge describes the target edge. 217*9e94795aSAndroid Build Coastguard Workerfunc (s TargetEdgePathSegment) Edge() *TargetEdge { 218*9e94795aSAndroid Build Coastguard Worker return s.edge 219*9e94795aSAndroid Build Coastguard Worker} 220*9e94795aSAndroid Build Coastguard Worker 221*9e94795aSAndroid Build Coastguard Worker// Annotations describes the type of edge by the set of annotations attached to 222*9e94795aSAndroid Build Coastguard Worker// it. 223*9e94795aSAndroid Build Coastguard Worker// 224*9e94795aSAndroid Build Coastguard Worker// Only annotations prescribed by policy have any meaning for licensing, and 225*9e94795aSAndroid Build Coastguard Worker// the meaning for licensing is likewise prescribed by policy. Other annotations 226*9e94795aSAndroid Build Coastguard Worker// are preserved and ignored by policy. 227*9e94795aSAndroid Build Coastguard Workerfunc (s TargetEdgePathSegment) Annotations() TargetEdgeAnnotations { 228*9e94795aSAndroid Build Coastguard Worker return s.edge.annotations 229*9e94795aSAndroid Build Coastguard Worker} 230*9e94795aSAndroid Build Coastguard Worker 231*9e94795aSAndroid Build Coastguard Worker// Context returns the context associated with the path segment. The type and 232*9e94795aSAndroid Build Coastguard Worker// value of the context defined by the process creating the path. 233*9e94795aSAndroid Build Coastguard Workerfunc (s TargetEdgePathSegment) Context() interface{} { 234*9e94795aSAndroid Build Coastguard Worker return s.ctx 235*9e94795aSAndroid Build Coastguard Worker} 236*9e94795aSAndroid Build Coastguard Worker 237*9e94795aSAndroid Build Coastguard Worker// String returns a human-readable string representation of the edge. 238*9e94795aSAndroid Build Coastguard Workerfunc (s TargetEdgePathSegment) String() string { 239*9e94795aSAndroid Build Coastguard Worker return fmt.Sprintf("%s -[%s]> %s", s.edge.target.name, strings.Join(s.edge.annotations.AsList(), ", "), s.edge.dependency.name) 240*9e94795aSAndroid Build Coastguard Worker} 241*9e94795aSAndroid Build Coastguard Worker 242*9e94795aSAndroid Build Coastguard Worker// TargetEdgePath describes a sequence of edges starting at a root and ending 243*9e94795aSAndroid Build Coastguard Worker// at some final dependency. 244*9e94795aSAndroid Build Coastguard Workertype TargetEdgePath []TargetEdgePathSegment 245*9e94795aSAndroid Build Coastguard Worker 246*9e94795aSAndroid Build Coastguard Worker// NewTargetEdgePath creates a new, empty path with capacity `cap`. 247*9e94795aSAndroid Build Coastguard Workerfunc NewTargetEdgePath(cap int) *TargetEdgePath { 248*9e94795aSAndroid Build Coastguard Worker p := make(TargetEdgePath, 0, cap) 249*9e94795aSAndroid Build Coastguard Worker return &p 250*9e94795aSAndroid Build Coastguard Worker} 251*9e94795aSAndroid Build Coastguard Worker 252*9e94795aSAndroid Build Coastguard Worker// Push appends a new edge to the list verifying that the target of the new 253*9e94795aSAndroid Build Coastguard Worker// edge is the dependency of the prior. 254*9e94795aSAndroid Build Coastguard Workerfunc (p *TargetEdgePath) Push(edge *TargetEdge, ctx interface{}) { 255*9e94795aSAndroid Build Coastguard Worker if len(*p) == 0 { 256*9e94795aSAndroid Build Coastguard Worker *p = append(*p, TargetEdgePathSegment{edge, ctx}) 257*9e94795aSAndroid Build Coastguard Worker return 258*9e94795aSAndroid Build Coastguard Worker } 259*9e94795aSAndroid Build Coastguard Worker if (*p)[len(*p)-1].edge.dependency != edge.target { 260*9e94795aSAndroid Build Coastguard Worker panic(fmt.Errorf("disjoint path %s does not end at %s", p.String(), edge.target.name)) 261*9e94795aSAndroid Build Coastguard Worker } 262*9e94795aSAndroid Build Coastguard Worker *p = append(*p, TargetEdgePathSegment{edge, ctx}) 263*9e94795aSAndroid Build Coastguard Worker} 264*9e94795aSAndroid Build Coastguard Worker 265*9e94795aSAndroid Build Coastguard Worker// Pop shortens the path by 1 edge. 266*9e94795aSAndroid Build Coastguard Workerfunc (p *TargetEdgePath) Pop() { 267*9e94795aSAndroid Build Coastguard Worker if len(*p) == 0 { 268*9e94795aSAndroid Build Coastguard Worker panic(fmt.Errorf("attempt to remove edge from empty path")) 269*9e94795aSAndroid Build Coastguard Worker } 270*9e94795aSAndroid Build Coastguard Worker *p = (*p)[:len(*p)-1] 271*9e94795aSAndroid Build Coastguard Worker} 272*9e94795aSAndroid Build Coastguard Worker 273*9e94795aSAndroid Build Coastguard Worker// Clear makes the path length 0. 274*9e94795aSAndroid Build Coastguard Workerfunc (p *TargetEdgePath) Clear() { 275*9e94795aSAndroid Build Coastguard Worker *p = (*p)[:0] 276*9e94795aSAndroid Build Coastguard Worker} 277*9e94795aSAndroid Build Coastguard Worker 278*9e94795aSAndroid Build Coastguard Worker// Copy makes a new path with the same value. 279*9e94795aSAndroid Build Coastguard Workerfunc (p *TargetEdgePath) Copy() *TargetEdgePath { 280*9e94795aSAndroid Build Coastguard Worker result := make(TargetEdgePath, 0, len(*p)) 281*9e94795aSAndroid Build Coastguard Worker for _, e := range *p { 282*9e94795aSAndroid Build Coastguard Worker result = append(result, e) 283*9e94795aSAndroid Build Coastguard Worker } 284*9e94795aSAndroid Build Coastguard Worker return &result 285*9e94795aSAndroid Build Coastguard Worker} 286*9e94795aSAndroid Build Coastguard Worker 287*9e94795aSAndroid Build Coastguard Worker// String returns a string representation of the path: [n1 -> n2 -> ... -> nn]. 288*9e94795aSAndroid Build Coastguard Workerfunc (p *TargetEdgePath) String() string { 289*9e94795aSAndroid Build Coastguard Worker if p == nil { 290*9e94795aSAndroid Build Coastguard Worker return "nil" 291*9e94795aSAndroid Build Coastguard Worker } 292*9e94795aSAndroid Build Coastguard Worker if len(*p) == 0 { 293*9e94795aSAndroid Build Coastguard Worker return "[]" 294*9e94795aSAndroid Build Coastguard Worker } 295*9e94795aSAndroid Build Coastguard Worker var sb strings.Builder 296*9e94795aSAndroid Build Coastguard Worker fmt.Fprintf(&sb, "[") 297*9e94795aSAndroid Build Coastguard Worker for _, s := range *p { 298*9e94795aSAndroid Build Coastguard Worker fmt.Fprintf(&sb, "%s -> ", s.edge.target.name) 299*9e94795aSAndroid Build Coastguard Worker } 300*9e94795aSAndroid Build Coastguard Worker lastSegment := (*p)[len(*p)-1] 301*9e94795aSAndroid Build Coastguard Worker fmt.Fprintf(&sb, "%s]", lastSegment.edge.dependency.name) 302*9e94795aSAndroid Build Coastguard Worker return sb.String() 303*9e94795aSAndroid Build Coastguard Worker} 304*9e94795aSAndroid Build Coastguard Worker 305*9e94795aSAndroid Build Coastguard Worker// TargetNode describes a module or target identified by the name of a specific 306*9e94795aSAndroid Build Coastguard Worker// metadata file. (immutable) 307*9e94795aSAndroid Build Coastguard Worker// 308*9e94795aSAndroid Build Coastguard Worker// Each metadata file corresponds to a Soong module or to a Make target. 309*9e94795aSAndroid Build Coastguard Worker// 310*9e94795aSAndroid Build Coastguard Worker// A target node can appear as the target or as the dependency in edges. 311*9e94795aSAndroid Build Coastguard Worker// Most target nodes appear as both target in one edge and as dependency in 312*9e94795aSAndroid Build Coastguard Worker// other edges. 313*9e94795aSAndroid Build Coastguard Workertype TargetNode targetNode 314*9e94795aSAndroid Build Coastguard Worker 315*9e94795aSAndroid Build Coastguard Worker// Name returns the string that identifies the target node. 316*9e94795aSAndroid Build Coastguard Worker// i.e. path to license metadata file 317*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) Name() string { 318*9e94795aSAndroid Build Coastguard Worker return tn.name 319*9e94795aSAndroid Build Coastguard Worker} 320*9e94795aSAndroid Build Coastguard Worker 321*9e94795aSAndroid Build Coastguard Worker// Dependencies returns the list of edges to dependencies of `tn`. 322*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) Dependencies() TargetEdgeList { 323*9e94795aSAndroid Build Coastguard Worker edges := make(TargetEdgeList, 0, len(tn.edges)) 324*9e94795aSAndroid Build Coastguard Worker edges = append(edges, tn.edges...) 325*9e94795aSAndroid Build Coastguard Worker return edges 326*9e94795aSAndroid Build Coastguard Worker} 327*9e94795aSAndroid Build Coastguard Worker 328*9e94795aSAndroid Build Coastguard Worker// PackageName returns the string that identifes the package for the target. 329*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) PackageName() string { 330*9e94795aSAndroid Build Coastguard Worker return tn.proto.GetPackageName() 331*9e94795aSAndroid Build Coastguard Worker} 332*9e94795aSAndroid Build Coastguard Worker 333*9e94795aSAndroid Build Coastguard Worker// ModuleName returns the module name of the target. 334*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) ModuleName() string { 335*9e94795aSAndroid Build Coastguard Worker return tn.proto.GetModuleName() 336*9e94795aSAndroid Build Coastguard Worker} 337*9e94795aSAndroid Build Coastguard Worker 338*9e94795aSAndroid Build Coastguard Worker// Projects returns the projects defining the target node. (unordered) 339*9e94795aSAndroid Build Coastguard Worker// 340*9e94795aSAndroid Build Coastguard Worker// In an ideal world, only 1 project defines a target, but the interaction 341*9e94795aSAndroid Build Coastguard Worker// between Soong and Make for a variety of architectures and for host versus 342*9e94795aSAndroid Build Coastguard Worker// product means a module is sometimes defined more than once. 343*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) Projects() []string { 344*9e94795aSAndroid Build Coastguard Worker return append([]string{}, tn.proto.Projects...) 345*9e94795aSAndroid Build Coastguard Worker} 346*9e94795aSAndroid Build Coastguard Worker 347*9e94795aSAndroid Build Coastguard Worker// LicenseConditions returns a copy of the set of license conditions 348*9e94795aSAndroid Build Coastguard Worker// originating at the target. The values that appear and how each is resolved 349*9e94795aSAndroid Build Coastguard Worker// is a matter of policy. (unordered) 350*9e94795aSAndroid Build Coastguard Worker// 351*9e94795aSAndroid Build Coastguard Worker// e.g. notice or proprietary 352*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) LicenseConditions() LicenseConditionSet { 353*9e94795aSAndroid Build Coastguard Worker return tn.licenseConditions 354*9e94795aSAndroid Build Coastguard Worker} 355*9e94795aSAndroid Build Coastguard Worker 356*9e94795aSAndroid Build Coastguard Worker// LicenseTexts returns the paths to the files containing the license texts for 357*9e94795aSAndroid Build Coastguard Worker// the target. (unordered) 358*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) LicenseTexts() []string { 359*9e94795aSAndroid Build Coastguard Worker return append([]string{}, tn.proto.LicenseTexts...) 360*9e94795aSAndroid Build Coastguard Worker} 361*9e94795aSAndroid Build Coastguard Worker 362*9e94795aSAndroid Build Coastguard Worker// IsContainer returns true if the target represents a container that merely 363*9e94795aSAndroid Build Coastguard Worker// aggregates other targets. 364*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) IsContainer() bool { 365*9e94795aSAndroid Build Coastguard Worker return tn.proto.GetIsContainer() 366*9e94795aSAndroid Build Coastguard Worker} 367*9e94795aSAndroid Build Coastguard Worker 368*9e94795aSAndroid Build Coastguard Worker// Built returns the list of files built by the module or target. (unordered) 369*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) Built() []string { 370*9e94795aSAndroid Build Coastguard Worker return append([]string{}, tn.proto.Built...) 371*9e94795aSAndroid Build Coastguard Worker} 372*9e94795aSAndroid Build Coastguard Worker 373*9e94795aSAndroid Build Coastguard Worker// Installed returns the list of files installed by the module or target. 374*9e94795aSAndroid Build Coastguard Worker// (unordered) 375*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) Installed() []string { 376*9e94795aSAndroid Build Coastguard Worker return append([]string{}, tn.proto.Installed...) 377*9e94795aSAndroid Build Coastguard Worker} 378*9e94795aSAndroid Build Coastguard Worker 379*9e94795aSAndroid Build Coastguard Worker// TargetFiles returns the list of files built or installed by the module or 380*9e94795aSAndroid Build Coastguard Worker// target. (unordered) 381*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) TargetFiles() []string { 382*9e94795aSAndroid Build Coastguard Worker return append(tn.proto.Built, tn.proto.Installed...) 383*9e94795aSAndroid Build Coastguard Worker} 384*9e94795aSAndroid Build Coastguard Worker 385*9e94795aSAndroid Build Coastguard Worker// InstallMap returns the list of path name transformations to make to move 386*9e94795aSAndroid Build Coastguard Worker// files from their original location in the file system to their destination 387*9e94795aSAndroid Build Coastguard Worker// inside a container. (unordered) 388*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) InstallMap() []InstallMap { 389*9e94795aSAndroid Build Coastguard Worker result := make([]InstallMap, 0, len(tn.proto.InstallMap)) 390*9e94795aSAndroid Build Coastguard Worker for _, im := range tn.proto.InstallMap { 391*9e94795aSAndroid Build Coastguard Worker result = append(result, InstallMap{im.GetFromPath(), im.GetContainerPath()}) 392*9e94795aSAndroid Build Coastguard Worker } 393*9e94795aSAndroid Build Coastguard Worker return result 394*9e94795aSAndroid Build Coastguard Worker} 395*9e94795aSAndroid Build Coastguard Worker 396*9e94795aSAndroid Build Coastguard Worker// Sources returns the list of file names depended on by the target, which may 397*9e94795aSAndroid Build Coastguard Worker// be a proper subset of those made available by dependency modules. 398*9e94795aSAndroid Build Coastguard Worker// (unordered) 399*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) Sources() []string { 400*9e94795aSAndroid Build Coastguard Worker return append([]string{}, tn.proto.Sources...) 401*9e94795aSAndroid Build Coastguard Worker} 402*9e94795aSAndroid Build Coastguard Worker 403*9e94795aSAndroid Build Coastguard Worker// InstallMap describes the mapping from an input filesystem file to file in a 404*9e94795aSAndroid Build Coastguard Worker// container. 405*9e94795aSAndroid Build Coastguard Workertype InstallMap struct { 406*9e94795aSAndroid Build Coastguard Worker // FromPath is the input path on the filesystem. 407*9e94795aSAndroid Build Coastguard Worker FromPath string 408*9e94795aSAndroid Build Coastguard Worker 409*9e94795aSAndroid Build Coastguard Worker // ContainerPath is the path to the same file inside the container or 410*9e94795aSAndroid Build Coastguard Worker // installed location. 411*9e94795aSAndroid Build Coastguard Worker ContainerPath string 412*9e94795aSAndroid Build Coastguard Worker} 413*9e94795aSAndroid Build Coastguard Worker 414*9e94795aSAndroid Build Coastguard Worker// TargetEdgeAnnotations describes an immutable set of annotations attached to 415*9e94795aSAndroid Build Coastguard Worker// an edge from a target to a dependency. 416*9e94795aSAndroid Build Coastguard Worker// 417*9e94795aSAndroid Build Coastguard Worker// Annotations typically distinguish between static linkage versus dynamic 418*9e94795aSAndroid Build Coastguard Worker// versus tools that are used at build time but are not linked in any way. 419*9e94795aSAndroid Build Coastguard Workertype TargetEdgeAnnotations struct { 420*9e94795aSAndroid Build Coastguard Worker annotations map[string]struct{} 421*9e94795aSAndroid Build Coastguard Worker} 422*9e94795aSAndroid Build Coastguard Worker 423*9e94795aSAndroid Build Coastguard Worker// newEdgeAnnotations creates a new instance of TargetEdgeAnnotations. 424*9e94795aSAndroid Build Coastguard Workerfunc newEdgeAnnotations() TargetEdgeAnnotations { 425*9e94795aSAndroid Build Coastguard Worker return TargetEdgeAnnotations{make(map[string]struct{})} 426*9e94795aSAndroid Build Coastguard Worker} 427*9e94795aSAndroid Build Coastguard Worker 428*9e94795aSAndroid Build Coastguard Worker// HasAnnotation returns true if an annotation `ann` is in the set. 429*9e94795aSAndroid Build Coastguard Workerfunc (ea TargetEdgeAnnotations) HasAnnotation(ann string) bool { 430*9e94795aSAndroid Build Coastguard Worker _, ok := ea.annotations[ann] 431*9e94795aSAndroid Build Coastguard Worker return ok 432*9e94795aSAndroid Build Coastguard Worker} 433*9e94795aSAndroid Build Coastguard Worker 434*9e94795aSAndroid Build Coastguard Worker// Compare orders TargetAnnotations returning: 435*9e94795aSAndroid Build Coastguard Worker// -1 when ea < other, 436*9e94795aSAndroid Build Coastguard Worker// +1 when ea > other, and 437*9e94795aSAndroid Build Coastguard Worker// 0 when ea == other. 438*9e94795aSAndroid Build Coastguard Workerfunc (ea TargetEdgeAnnotations) Compare(other TargetEdgeAnnotations) int { 439*9e94795aSAndroid Build Coastguard Worker a1 := ea.AsList() 440*9e94795aSAndroid Build Coastguard Worker a2 := other.AsList() 441*9e94795aSAndroid Build Coastguard Worker sort.Strings(a1) 442*9e94795aSAndroid Build Coastguard Worker sort.Strings(a2) 443*9e94795aSAndroid Build Coastguard Worker for k := 0; k < len(a1) && k < len(a2); k++ { 444*9e94795aSAndroid Build Coastguard Worker if a1[k] < a2[k] { 445*9e94795aSAndroid Build Coastguard Worker return -1 446*9e94795aSAndroid Build Coastguard Worker } 447*9e94795aSAndroid Build Coastguard Worker if a1[k] > a2[k] { 448*9e94795aSAndroid Build Coastguard Worker return 1 449*9e94795aSAndroid Build Coastguard Worker } 450*9e94795aSAndroid Build Coastguard Worker } 451*9e94795aSAndroid Build Coastguard Worker if len(a1) < len(a2) { 452*9e94795aSAndroid Build Coastguard Worker return -1 453*9e94795aSAndroid Build Coastguard Worker } 454*9e94795aSAndroid Build Coastguard Worker if len(a1) > len(a2) { 455*9e94795aSAndroid Build Coastguard Worker return 1 456*9e94795aSAndroid Build Coastguard Worker } 457*9e94795aSAndroid Build Coastguard Worker return 0 458*9e94795aSAndroid Build Coastguard Worker} 459*9e94795aSAndroid Build Coastguard Worker 460*9e94795aSAndroid Build Coastguard Worker// AsList returns the list of annotation names attached to the edge. 461*9e94795aSAndroid Build Coastguard Worker// (unordered) 462*9e94795aSAndroid Build Coastguard Workerfunc (ea TargetEdgeAnnotations) AsList() []string { 463*9e94795aSAndroid Build Coastguard Worker l := make([]string, 0, len(ea.annotations)) 464*9e94795aSAndroid Build Coastguard Worker for ann := range ea.annotations { 465*9e94795aSAndroid Build Coastguard Worker l = append(l, ann) 466*9e94795aSAndroid Build Coastguard Worker } 467*9e94795aSAndroid Build Coastguard Worker return l 468*9e94795aSAndroid Build Coastguard Worker} 469*9e94795aSAndroid Build Coastguard Worker 470*9e94795aSAndroid Build Coastguard Worker// TargetNodeSet describes a set of distinct nodes in a license graph. 471*9e94795aSAndroid Build Coastguard Workertype TargetNodeSet map[*TargetNode]struct{} 472*9e94795aSAndroid Build Coastguard Worker 473*9e94795aSAndroid Build Coastguard Worker// Contains returns true when `target` is an element of the set. 474*9e94795aSAndroid Build Coastguard Workerfunc (ts TargetNodeSet) Contains(target *TargetNode) bool { 475*9e94795aSAndroid Build Coastguard Worker _, isPresent := ts[target] 476*9e94795aSAndroid Build Coastguard Worker return isPresent 477*9e94795aSAndroid Build Coastguard Worker} 478*9e94795aSAndroid Build Coastguard Worker 479*9e94795aSAndroid Build Coastguard Worker// Names returns the array of target node namess in the set. (unordered) 480*9e94795aSAndroid Build Coastguard Workerfunc (ts TargetNodeSet) Names() []string { 481*9e94795aSAndroid Build Coastguard Worker result := make([]string, 0, len(ts)) 482*9e94795aSAndroid Build Coastguard Worker for tn := range ts { 483*9e94795aSAndroid Build Coastguard Worker result = append(result, tn.name) 484*9e94795aSAndroid Build Coastguard Worker } 485*9e94795aSAndroid Build Coastguard Worker return result 486*9e94795aSAndroid Build Coastguard Worker} 487*9e94795aSAndroid Build Coastguard Worker 488*9e94795aSAndroid Build Coastguard Worker// String returns a human-readable string representation of the set. 489*9e94795aSAndroid Build Coastguard Workerfunc (ts TargetNodeSet) String() string { 490*9e94795aSAndroid Build Coastguard Worker return fmt.Sprintf("{%s}", strings.Join(ts.Names(), ", ")) 491*9e94795aSAndroid Build Coastguard Worker} 492*9e94795aSAndroid Build Coastguard Worker 493*9e94795aSAndroid Build Coastguard Worker// TargetNodeList orders a list of targets by name. 494*9e94795aSAndroid Build Coastguard Workertype TargetNodeList []*TargetNode 495*9e94795aSAndroid Build Coastguard Worker 496*9e94795aSAndroid Build Coastguard Worker// Len returns the count of elements in the list. 497*9e94795aSAndroid Build Coastguard Workerfunc (l TargetNodeList) Len() int { return len(l) } 498*9e94795aSAndroid Build Coastguard Worker 499*9e94795aSAndroid Build Coastguard Worker// Swap rearranges 2 elements so that each occupies the other's former position. 500*9e94795aSAndroid Build Coastguard Workerfunc (l TargetNodeList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 501*9e94795aSAndroid Build Coastguard Worker 502*9e94795aSAndroid Build Coastguard Worker// Less returns true when the `i`th element is lexicographicallt less than the `j`th. 503*9e94795aSAndroid Build Coastguard Workerfunc (l TargetNodeList) Less(i, j int) bool { 504*9e94795aSAndroid Build Coastguard Worker return l[i].name < l[j].name 505*9e94795aSAndroid Build Coastguard Worker} 506*9e94795aSAndroid Build Coastguard Worker 507*9e94795aSAndroid Build Coastguard Worker// String returns a string representation of the list. 508*9e94795aSAndroid Build Coastguard Workerfunc (l TargetNodeList) String() string { 509*9e94795aSAndroid Build Coastguard Worker var sb strings.Builder 510*9e94795aSAndroid Build Coastguard Worker fmt.Fprintf(&sb, "[") 511*9e94795aSAndroid Build Coastguard Worker sep := "" 512*9e94795aSAndroid Build Coastguard Worker for _, tn := range l { 513*9e94795aSAndroid Build Coastguard Worker fmt.Fprintf(&sb, "%s%s", sep, tn.name) 514*9e94795aSAndroid Build Coastguard Worker sep = " " 515*9e94795aSAndroid Build Coastguard Worker } 516*9e94795aSAndroid Build Coastguard Worker fmt.Fprintf(&sb, "]") 517*9e94795aSAndroid Build Coastguard Worker return sb.String() 518*9e94795aSAndroid Build Coastguard Worker} 519*9e94795aSAndroid Build Coastguard Worker 520*9e94795aSAndroid Build Coastguard Worker// Names returns an array the names of the nodes in the same order as the nodes in the list. 521*9e94795aSAndroid Build Coastguard Workerfunc (l TargetNodeList) Names() []string { 522*9e94795aSAndroid Build Coastguard Worker result := make([]string, 0, len(l)) 523*9e94795aSAndroid Build Coastguard Worker for _, tn := range l { 524*9e94795aSAndroid Build Coastguard Worker result = append(result, tn.name) 525*9e94795aSAndroid Build Coastguard Worker } 526*9e94795aSAndroid Build Coastguard Worker return result 527*9e94795aSAndroid Build Coastguard Worker} 528