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