aboutsummaryrefslogtreecommitdiff
path: root/licensediff/licensediff.go
blob: ba8cd84c129d99be0754296ab689e233c0d3293b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Package licensediff is used to generate a "diff" between the concluded
// licenses in two SPDX Packages, using the filename as the match point.
// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
package licensediff

import (
	"github.com/spdx/tools-golang/spdx/v2_1"
	"github.com/spdx/tools-golang/spdx/v2_2"
	"github.com/spdx/tools-golang/spdx/v2_3"
)

// LicensePair is a result set where we are talking about two license strings,
// potentially differing, for a single filename between two SPDX Packages.
type LicensePair struct {
	First  string
	Second string
}

// MakePairs2_1 essentially just consolidates all files and LicenseConcluded
// strings into a single data structure.
func MakePairs2_1(p1 *v2_1.Package, p2 *v2_1.Package) (map[string]LicensePair, error) {
	pairs := map[string]LicensePair{}

	// first, go through and add all files/licenses from p1
	for _, f := range p1.Files {
		pair := LicensePair{First: f.LicenseConcluded, Second: ""}
		pairs[f.FileName] = pair
	}

	// now, go through all files/licenses from p2. If already
	// present, add as .second; if not, create new pair
	for _, f := range p2.Files {
		firstLic := ""
		existingPair, ok := pairs[f.FileName]
		if ok {
			// already present; update it
			firstLic = existingPair.First
		}
		// now, update what's there, either way
		pair := LicensePair{First: firstLic, Second: f.LicenseConcluded}
		pairs[f.FileName] = pair
	}

	return pairs, nil
}

// MakePairs2_2 essentially just consolidates all files and LicenseConcluded
// strings into a single data structure.
func MakePairs2_2(p1 *v2_2.Package, p2 *v2_2.Package) (map[string]LicensePair, error) {
	pairs := map[string]LicensePair{}

	// first, go through and add all files/licenses from p1
	for _, f := range p1.Files {
		pair := LicensePair{First: f.LicenseConcluded, Second: ""}
		pairs[f.FileName] = pair
	}

	// now, go through all files/licenses from p2. If already
	// present, add as .second; if not, create new pair
	for _, f := range p2.Files {
		firstLic := ""
		existingPair, ok := pairs[f.FileName]
		if ok {
			// already present; update it
			firstLic = existingPair.First
		}
		// now, update what's there, either way
		pair := LicensePair{First: firstLic, Second: f.LicenseConcluded}
		pairs[f.FileName] = pair
	}

	return pairs, nil
}

// MakePairs2_3 essentially just consolidates all files and LicenseConcluded
// strings into a single data structure.
func MakePairs2_3(p1 *v2_3.Package, p2 *v2_3.Package) (map[string]LicensePair, error) {
	pairs := map[string]LicensePair{}

	// first, go through and add all files/licenses from p1
	for _, f := range p1.Files {
		pair := LicensePair{First: f.LicenseConcluded, Second: ""}
		pairs[f.FileName] = pair
	}

	// now, go through all files/licenses from p2. If already
	// present, add as .second; if not, create new pair
	for _, f := range p2.Files {
		firstLic := ""
		existingPair, ok := pairs[f.FileName]
		if ok {
			// already present; update it
			firstLic = existingPair.First
		}
		// now, update what's there, either way
		pair := LicensePair{First: firstLic, Second: f.LicenseConcluded}
		pairs[f.FileName] = pair
	}

	return pairs, nil
}

// LicenseDiff is a structured version of the output of MakePairs. It is
// meant to make it easier to find and report on, e.g., just the files that
// have different licenses, or those that are in just one scan.
type LicenseDiff struct {
	InBothChanged map[string]LicensePair
	InBothSame    map[string]string
	InFirstOnly   map[string]string
	InSecondOnly  map[string]string
}

// MakeResults creates a more structured set of results from the output
// of MakePairs.
func MakeResults(pairs map[string]LicensePair) (*LicenseDiff, error) {
	diff := &LicenseDiff{
		InBothChanged: map[string]LicensePair{},
		InBothSame:    map[string]string{},
		InFirstOnly:   map[string]string{},
		InSecondOnly:  map[string]string{},
	}

	// walk through pairs and allocate them where they belong
	for filename, pair := range pairs {
		if pair.First == pair.Second {
			diff.InBothSame[filename] = pair.First
		} else {
			if pair.First == "" {
				diff.InSecondOnly[filename] = pair.Second
			} else if pair.Second == "" {
				diff.InFirstOnly[filename] = pair.First
			} else {
				diff.InBothChanged[filename] = pair
			}
		}
	}

	return diff, nil
}