1// Package licensediff is used to generate a "diff" between the concluded 2// licenses in two SPDX Packages, using the filename as the match point. 3// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 4package licensediff 5 6import ( 7 "github.com/spdx/tools-golang/spdx/v2_1" 8 "github.com/spdx/tools-golang/spdx/v2_2" 9 "github.com/spdx/tools-golang/spdx/v2_3" 10) 11 12// LicensePair is a result set where we are talking about two license strings, 13// potentially differing, for a single filename between two SPDX Packages. 14type LicensePair struct { 15 First string 16 Second string 17} 18 19// MakePairs2_1 essentially just consolidates all files and LicenseConcluded 20// strings into a single data structure. 21func MakePairs2_1(p1 *v2_1.Package, p2 *v2_1.Package) (map[string]LicensePair, error) { 22 pairs := map[string]LicensePair{} 23 24 // first, go through and add all files/licenses from p1 25 for _, f := range p1.Files { 26 pair := LicensePair{First: f.LicenseConcluded, Second: ""} 27 pairs[f.FileName] = pair 28 } 29 30 // now, go through all files/licenses from p2. If already 31 // present, add as .second; if not, create new pair 32 for _, f := range p2.Files { 33 firstLic := "" 34 existingPair, ok := pairs[f.FileName] 35 if ok { 36 // already present; update it 37 firstLic = existingPair.First 38 } 39 // now, update what's there, either way 40 pair := LicensePair{First: firstLic, Second: f.LicenseConcluded} 41 pairs[f.FileName] = pair 42 } 43 44 return pairs, nil 45} 46 47// MakePairs2_2 essentially just consolidates all files and LicenseConcluded 48// strings into a single data structure. 49func MakePairs2_2(p1 *v2_2.Package, p2 *v2_2.Package) (map[string]LicensePair, error) { 50 pairs := map[string]LicensePair{} 51 52 // first, go through and add all files/licenses from p1 53 for _, f := range p1.Files { 54 pair := LicensePair{First: f.LicenseConcluded, Second: ""} 55 pairs[f.FileName] = pair 56 } 57 58 // now, go through all files/licenses from p2. If already 59 // present, add as .second; if not, create new pair 60 for _, f := range p2.Files { 61 firstLic := "" 62 existingPair, ok := pairs[f.FileName] 63 if ok { 64 // already present; update it 65 firstLic = existingPair.First 66 } 67 // now, update what's there, either way 68 pair := LicensePair{First: firstLic, Second: f.LicenseConcluded} 69 pairs[f.FileName] = pair 70 } 71 72 return pairs, nil 73} 74 75// MakePairs2_3 essentially just consolidates all files and LicenseConcluded 76// strings into a single data structure. 77func MakePairs2_3(p1 *v2_3.Package, p2 *v2_3.Package) (map[string]LicensePair, error) { 78 pairs := map[string]LicensePair{} 79 80 // first, go through and add all files/licenses from p1 81 for _, f := range p1.Files { 82 pair := LicensePair{First: f.LicenseConcluded, Second: ""} 83 pairs[f.FileName] = pair 84 } 85 86 // now, go through all files/licenses from p2. If already 87 // present, add as .second; if not, create new pair 88 for _, f := range p2.Files { 89 firstLic := "" 90 existingPair, ok := pairs[f.FileName] 91 if ok { 92 // already present; update it 93 firstLic = existingPair.First 94 } 95 // now, update what's there, either way 96 pair := LicensePair{First: firstLic, Second: f.LicenseConcluded} 97 pairs[f.FileName] = pair 98 } 99 100 return pairs, nil 101} 102 103// LicenseDiff is a structured version of the output of MakePairs. It is 104// meant to make it easier to find and report on, e.g., just the files that 105// have different licenses, or those that are in just one scan. 106type LicenseDiff struct { 107 InBothChanged map[string]LicensePair 108 InBothSame map[string]string 109 InFirstOnly map[string]string 110 InSecondOnly map[string]string 111} 112 113// MakeResults creates a more structured set of results from the output 114// of MakePairs. 115func MakeResults(pairs map[string]LicensePair) (*LicenseDiff, error) { 116 diff := &LicenseDiff{ 117 InBothChanged: map[string]LicensePair{}, 118 InBothSame: map[string]string{}, 119 InFirstOnly: map[string]string{}, 120 InSecondOnly: map[string]string{}, 121 } 122 123 // walk through pairs and allocate them where they belong 124 for filename, pair := range pairs { 125 if pair.First == pair.Second { 126 diff.InBothSame[filename] = pair.First 127 } else { 128 if pair.First == "" { 129 diff.InSecondOnly[filename] = pair.Second 130 } else if pair.Second == "" { 131 diff.InFirstOnly[filename] = pair.First 132 } else { 133 diff.InBothChanged[filename] = pair 134 } 135 } 136 } 137 138 return diff, nil 139} 140