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) 20*9e94795aSAndroid Build Coastguard Worker 21*9e94795aSAndroid Build Coastguard Worker// SourceSharePrivacyConflict describes an individual conflict between a source-sharing 22*9e94795aSAndroid Build Coastguard Worker// condition and a source privacy condition 23*9e94795aSAndroid Build Coastguard Workertype SourceSharePrivacyConflict struct { 24*9e94795aSAndroid Build Coastguard Worker SourceNode *TargetNode 25*9e94795aSAndroid Build Coastguard Worker ShareCondition LicenseCondition 26*9e94795aSAndroid Build Coastguard Worker PrivacyCondition LicenseCondition 27*9e94795aSAndroid Build Coastguard Worker} 28*9e94795aSAndroid Build Coastguard Worker 29*9e94795aSAndroid Build Coastguard Worker// Error returns a string describing the conflict. 30*9e94795aSAndroid Build Coastguard Workerfunc (conflict SourceSharePrivacyConflict) Error() string { 31*9e94795aSAndroid Build Coastguard Worker return fmt.Sprintf("%s %s and must share from %s condition\n", conflict.SourceNode.name, 32*9e94795aSAndroid Build Coastguard Worker conflict.PrivacyCondition.Name(), conflict.ShareCondition.Name()) 33*9e94795aSAndroid Build Coastguard Worker} 34*9e94795aSAndroid Build Coastguard Worker 35*9e94795aSAndroid Build Coastguard Worker// IsEqualTo returns true when `conflict` and `other` describe the same conflict. 36*9e94795aSAndroid Build Coastguard Workerfunc (conflict SourceSharePrivacyConflict) IsEqualTo(other SourceSharePrivacyConflict) bool { 37*9e94795aSAndroid Build Coastguard Worker return conflict.SourceNode.name == other.SourceNode.name && 38*9e94795aSAndroid Build Coastguard Worker conflict.ShareCondition == other.ShareCondition && 39*9e94795aSAndroid Build Coastguard Worker conflict.PrivacyCondition == other.PrivacyCondition 40*9e94795aSAndroid Build Coastguard Worker} 41*9e94795aSAndroid Build Coastguard Worker 42*9e94795aSAndroid Build Coastguard Worker// ConflictingSharedPrivateSource lists all of the targets where conflicting conditions to 43*9e94795aSAndroid Build Coastguard Worker// share the source and to keep the source private apply to the target. 44*9e94795aSAndroid Build Coastguard Workerfunc ConflictingSharedPrivateSource(lg *LicenseGraph) []SourceSharePrivacyConflict { 45*9e94795aSAndroid Build Coastguard Worker 46*9e94795aSAndroid Build Coastguard Worker ResolveTopDownConditions(lg) 47*9e94795aSAndroid Build Coastguard Worker // combined is the combination of source-sharing and source privacy. 48*9e94795aSAndroid Build Coastguard Worker combined := WalkActionsForCondition(lg, ImpliesShared.Union(ImpliesPrivate)) 49*9e94795aSAndroid Build Coastguard Worker 50*9e94795aSAndroid Build Coastguard Worker // size is the size of the result 51*9e94795aSAndroid Build Coastguard Worker size := 0 52*9e94795aSAndroid Build Coastguard Worker for actsOn, cs := range combined { 53*9e94795aSAndroid Build Coastguard Worker if actsOn.pure && !actsOn.LicenseConditions().MatchesAnySet(ImpliesShared) { 54*9e94795aSAndroid Build Coastguard Worker // no need to share code to build "a distribution medium" 55*9e94795aSAndroid Build Coastguard Worker continue 56*9e94795aSAndroid Build Coastguard Worker } 57*9e94795aSAndroid Build Coastguard Worker size += cs.Intersection(ImpliesShared).Len() * cs.Intersection(ImpliesPrivate).Len() 58*9e94795aSAndroid Build Coastguard Worker } 59*9e94795aSAndroid Build Coastguard Worker if size == 0 { 60*9e94795aSAndroid Build Coastguard Worker return nil 61*9e94795aSAndroid Build Coastguard Worker } 62*9e94795aSAndroid Build Coastguard Worker result := make([]SourceSharePrivacyConflict, 0, size) 63*9e94795aSAndroid Build Coastguard Worker for actsOn, cs := range combined { 64*9e94795aSAndroid Build Coastguard Worker if actsOn.pure { // no need to share code for "a distribution medium" 65*9e94795aSAndroid Build Coastguard Worker continue 66*9e94795aSAndroid Build Coastguard Worker } 67*9e94795aSAndroid Build Coastguard Worker pconditions := cs.Intersection(ImpliesPrivate).AsList() 68*9e94795aSAndroid Build Coastguard Worker ssconditions := cs.Intersection(ImpliesShared).AsList() 69*9e94795aSAndroid Build Coastguard Worker 70*9e94795aSAndroid Build Coastguard Worker // report all conflicting condition combinations 71*9e94795aSAndroid Build Coastguard Worker for _, p := range pconditions { 72*9e94795aSAndroid Build Coastguard Worker for _, ss := range ssconditions { 73*9e94795aSAndroid Build Coastguard Worker result = append(result, SourceSharePrivacyConflict{actsOn, ss, p}) 74*9e94795aSAndroid Build Coastguard Worker } 75*9e94795aSAndroid Build Coastguard Worker } 76*9e94795aSAndroid Build Coastguard Worker } 77*9e94795aSAndroid Build Coastguard Worker return result 78*9e94795aSAndroid Build Coastguard Worker} 79