Bob Badour | a99ac62 | 2021-10-25 16:21:00 -0700 | [diff] [blame] | 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 | |
| 15 | package compliance |
| 16 | |
| 17 | import ( |
| 18 | "fmt" |
| 19 | "strings" |
| 20 | ) |
| 21 | |
Bob Badour | a99ac62 | 2021-10-25 16:21:00 -0700 | [diff] [blame] | 22 | // ResolutionSet describes an immutable set of targets and the license |
| 23 | // conditions each target must satisfy or "resolve" in a specific context. |
| 24 | // |
| 25 | // Ultimately, the purpose of recording the license metadata and building a |
| 26 | // license graph is to identify, describe, and verify the necessary actions or |
| 27 | // operations for compliance policy. |
| 28 | // |
| 29 | // i.e. What is the source-sharing policy? Has it been met? Meet it. |
| 30 | // |
| 31 | // i.e. Are there incompatible policy requirements? Such as a source-sharing |
| 32 | // policy applied to code that policy also says may not be shared? If so, stop |
| 33 | // and remove the dependencies that create the situation. |
| 34 | // |
| 35 | // The ResolutionSet is the base unit for mapping license conditions to the |
| 36 | // targets triggering some necessary action per policy. Different ResolutionSet |
| 37 | // values may be calculated for different contexts. |
| 38 | // |
| 39 | // e.g. Suppose an unencumbered binary links in a notice .a library. |
| 40 | // |
| 41 | // An "unencumbered" condition would originate from the binary, and a "notice" |
| 42 | // condition would originate from the .a library. A ResolutionSet for the |
Bob Badour | 103eb0f | 2022-01-10 13:50:57 -0800 | [diff] [blame^] | 43 | // context of the Notice policy might attach both conditions to the binary to |
| 44 | // act on the origin of each condition. By attaching the notice condition to |
Bob Badour | a99ac62 | 2021-10-25 16:21:00 -0700 | [diff] [blame] | 45 | // the binary, the ResolutionSet stipulates the policy that the release of the |
| 46 | // unencumbered binary must provide suitable notice for the .a library. |
| 47 | // |
| 48 | // The resulting ResolutionSet could be used for building a notice file, for |
| 49 | // validating that a suitable notice has been built into the distribution, or |
| 50 | // for reporting what notices need to be given. |
| 51 | // |
Bob Badour | 103eb0f | 2022-01-10 13:50:57 -0800 | [diff] [blame^] | 52 | // The action is defined by the context. In the above example, the action is |
| 53 | // providing notice for the module acted on. In another context, the action |
| 54 | // might be sharing the source-code or preserving the privacy of the module |
| 55 | // acted on. |
| 56 | type ResolutionSet map[*TargetNode]ActionSet |
| 57 | |
| 58 | // AttachesTo identifies the list of targets triggering action to resolve |
| 59 | // conditions. (unordered) |
| 60 | func (rs ResolutionSet) AttachesTo() TargetNodeList { |
| 61 | result := make(TargetNodeList, 0, len(rs)) |
| 62 | for attachesTo := range rs { |
| 63 | result = append(result, attachesTo) |
| 64 | } |
| 65 | return result |
Bob Badour | a99ac62 | 2021-10-25 16:21:00 -0700 | [diff] [blame] | 66 | } |
| 67 | |
Bob Badour | 103eb0f | 2022-01-10 13:50:57 -0800 | [diff] [blame^] | 68 | |
| 69 | // AttachesToTarget returns true if the set contains conditions that |
| 70 | // are `attachedTo`. |
| 71 | func (rs ResolutionSet) AttachesToTarget(target *TargetNode) bool { |
| 72 | _, isPresent := rs[target] |
| 73 | return isPresent |
| 74 | } |
| 75 | |
| 76 | |
| 77 | // Resolutions returns the list of resolutions that `attachedTo` |
| 78 | // target must resolve. Returns empty list if no conditions apply. |
| 79 | func (rs ResolutionSet) Resolutions(attachesTo *TargetNode) ResolutionList { |
| 80 | as, ok := rs[attachesTo] |
| 81 | if !ok { |
| 82 | return nil |
| 83 | } |
| 84 | result := make(ResolutionList, 0, len(as)) |
| 85 | for actsOn, cs := range as { |
| 86 | result = append(result, Resolution{attachesTo, actsOn, cs}) |
| 87 | } |
| 88 | return result |
| 89 | } |
| 90 | |
| 91 | // String returns a human-readable string representation of the set. |
| 92 | func (rs ResolutionSet) String() string { |
Bob Badour | a99ac62 | 2021-10-25 16:21:00 -0700 | [diff] [blame] | 93 | var sb strings.Builder |
| 94 | fmt.Fprintf(&sb, "{") |
| 95 | sep := "" |
Bob Badour | 103eb0f | 2022-01-10 13:50:57 -0800 | [diff] [blame^] | 96 | for attachesTo, as := range rs { |
| 97 | fmt.Fprintf(&sb, "%s%s -> %s", sep, attachesTo.Name(), as.String()) |
Bob Badour | a99ac62 | 2021-10-25 16:21:00 -0700 | [diff] [blame] | 98 | sep = ", " |
| 99 | } |
| 100 | fmt.Fprintf(&sb, "}") |
| 101 | return sb.String() |
| 102 | } |
| 103 | |
Bob Badour | 103eb0f | 2022-01-10 13:50:57 -0800 | [diff] [blame^] | 104 | // ActionSet identifies a set of targets to act on and the license conditions |
| 105 | // the action will resolve. |
| 106 | type ActionSet map[*TargetNode]LicenseConditionSet |
Bob Badour | a99ac62 | 2021-10-25 16:21:00 -0700 | [diff] [blame] | 107 | |
Bob Badour | 103eb0f | 2022-01-10 13:50:57 -0800 | [diff] [blame^] | 108 | // String returns a human-readable string representation of the set. |
| 109 | func (as ActionSet) String() string { |
| 110 | var sb strings.Builder |
| 111 | fmt.Fprintf(&sb, "{") |
| 112 | sep := "" |
Bob Badour | a99ac62 | 2021-10-25 16:21:00 -0700 | [diff] [blame] | 113 | for actsOn, cs := range as { |
Bob Badour | 103eb0f | 2022-01-10 13:50:57 -0800 | [diff] [blame^] | 114 | fmt.Fprintf(&sb, "%s%s%s", sep, actsOn.Name(), cs.String()) |
| 115 | sep = ", " |
Bob Badour | a99ac62 | 2021-10-25 16:21:00 -0700 | [diff] [blame] | 116 | } |
Bob Badour | 103eb0f | 2022-01-10 13:50:57 -0800 | [diff] [blame^] | 117 | fmt.Fprintf(&sb, "}") |
| 118 | return sb.String() |
Bob Badour | a99ac62 | 2021-10-25 16:21:00 -0700 | [diff] [blame] | 119 | } |