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