xref: /aosp_15_r20/external/spdx-tools/examples/6-licensediff/example_licensediff.go (revision ba677afa8f67bb56cbc794f4d0e378e0da058e16)
1*ba677afaSXin Li// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2*ba677afaSXin Li
3*ba677afaSXin Li// Example for: *licensediff*, *tvloader*
4*ba677afaSXin Li
5*ba677afaSXin Li// This example demonstrates loading two SPDX tag-value files from disk into
6*ba677afaSXin Li// memory, and generating a diff of the concluded licenses for Files in
7*ba677afaSXin Li// Packages with matching IDs in each document.
8*ba677afaSXin Li// This is generally only useful when run with two SPDX documents that
9*ba677afaSXin Li// describe licenses for subsequent versions of the same set of files, AND if
10*ba677afaSXin Li// they have the same identifier in both documents.
11*ba677afaSXin Li// Run project: go run example_licensediff.go ../sample-docs/tv/hello.spdx  ../sample-docs/tv/hello-modified.spdx
12*ba677afaSXin Lipackage main
13*ba677afaSXin Li
14*ba677afaSXin Liimport (
15*ba677afaSXin Li	"fmt"
16*ba677afaSXin Li	"os"
17*ba677afaSXin Li
18*ba677afaSXin Li	"github.com/spdx/tools-golang/licensediff"
19*ba677afaSXin Li	"github.com/spdx/tools-golang/spdx/v2_2"
20*ba677afaSXin Li	"github.com/spdx/tools-golang/spdxlib"
21*ba677afaSXin Li	"github.com/spdx/tools-golang/tvloader"
22*ba677afaSXin Li)
23*ba677afaSXin Li
24*ba677afaSXin Lifunc main() {
25*ba677afaSXin Li
26*ba677afaSXin Li	// check that we've received the right number of arguments
27*ba677afaSXin Li	args := os.Args
28*ba677afaSXin Li	if len(args) != 3 {
29*ba677afaSXin Li		fmt.Printf("Usage: %v <spdx-file-first> <spdx-file-second>\n", args[0])
30*ba677afaSXin Li		fmt.Printf("  Load SPDX 2.2 tag-value files <spdx-file-first> and <spdx-file-second>,\n")
31*ba677afaSXin Li		fmt.Printf("  run a diff between their concluded licenses, and print basic results.\n")
32*ba677afaSXin Li		return
33*ba677afaSXin Li	}
34*ba677afaSXin Li
35*ba677afaSXin Li	// open the first SPDX file
36*ba677afaSXin Li	filenameFirst := args[1]
37*ba677afaSXin Li	r, err := os.Open(filenameFirst)
38*ba677afaSXin Li	if err != nil {
39*ba677afaSXin Li		fmt.Printf("Error while opening %v for reading: %v", filenameFirst, err)
40*ba677afaSXin Li		return
41*ba677afaSXin Li	}
42*ba677afaSXin Li	defer r.Close()
43*ba677afaSXin Li
44*ba677afaSXin Li	// try to load the first SPDX file's contents as a tag-value file, version 2.2
45*ba677afaSXin Li	docFirst, err := tvloader.Load2_2(r)
46*ba677afaSXin Li	if err != nil {
47*ba677afaSXin Li		fmt.Printf("Error while parsing %v: %v", filenameFirst, err)
48*ba677afaSXin Li		return
49*ba677afaSXin Li	}
50*ba677afaSXin Li	// check whether the SPDX file has at least one package that it describes
51*ba677afaSXin Li	pkgIDsFirst, err := spdxlib.GetDescribedPackageIDs2_2(docFirst)
52*ba677afaSXin Li	if err != nil {
53*ba677afaSXin Li		fmt.Printf("Unable to get describe packages from first SPDX document: %v\n", err)
54*ba677afaSXin Li		return
55*ba677afaSXin Li	}
56*ba677afaSXin Li
57*ba677afaSXin Li	// if we got here, the file is now loaded into memory.
58*ba677afaSXin Li	fmt.Printf("Successfully loaded first SPDX file %s\n", filenameFirst)
59*ba677afaSXin Li
60*ba677afaSXin Li	// open the second SPDX file
61*ba677afaSXin Li	filenameSecond := args[2]
62*ba677afaSXin Li	r, err = os.Open(filenameSecond)
63*ba677afaSXin Li	if err != nil {
64*ba677afaSXin Li		fmt.Printf("Error while opening %v for reading: %v", filenameSecond, err)
65*ba677afaSXin Li		return
66*ba677afaSXin Li	}
67*ba677afaSXin Li	defer r.Close()
68*ba677afaSXin Li
69*ba677afaSXin Li	// try to load the second SPDX file's contents as a tag-value file, version 2.2
70*ba677afaSXin Li	docSecond, err := tvloader.Load2_2(r)
71*ba677afaSXin Li	if err != nil {
72*ba677afaSXin Li		fmt.Printf("Error while parsing %v: %v", filenameSecond, err)
73*ba677afaSXin Li		return
74*ba677afaSXin Li	}
75*ba677afaSXin Li	// check whether the SPDX file has at least one package that it describes
76*ba677afaSXin Li	pkgIDsSecond, err := spdxlib.GetDescribedPackageIDs2_2(docSecond)
77*ba677afaSXin Li	if err != nil {
78*ba677afaSXin Li		fmt.Printf("Unable to get describe packages from second SPDX document: %v\n", err)
79*ba677afaSXin Li		return
80*ba677afaSXin Li	}
81*ba677afaSXin Li
82*ba677afaSXin Li	// if we got here, the file is now loaded into memory.
83*ba677afaSXin Li	fmt.Printf("Successfully loaded second SPDX file %s\n\n", filenameSecond)
84*ba677afaSXin Li
85*ba677afaSXin Li	// compare the described packages from each Document, by SPDX ID
86*ba677afaSXin Li	// go through the first set first, report if they aren't in the second set
87*ba677afaSXin Li	for _, pkgID := range pkgIDsFirst {
88*ba677afaSXin Li		fmt.Printf("================================\n")
89*ba677afaSXin Li
90*ba677afaSXin Li		var p1, p2 *v2_2.Package
91*ba677afaSXin Li		var okFirst, okSecond bool
92*ba677afaSXin Li		for _, pkg := range docFirst.Packages {
93*ba677afaSXin Li			if pkg.PackageSPDXIdentifier == pkgID {
94*ba677afaSXin Li				okFirst = true
95*ba677afaSXin Li				p1 = pkg
96*ba677afaSXin Li				break
97*ba677afaSXin Li			}
98*ba677afaSXin Li		}
99*ba677afaSXin Li		if !okFirst {
100*ba677afaSXin Li			fmt.Printf("Package %s has described relationship in first document but ID not found\n", string(pkgID))
101*ba677afaSXin Li			continue
102*ba677afaSXin Li		}
103*ba677afaSXin Li
104*ba677afaSXin Li		fmt.Printf("Package %s (%s)\n", string(pkgID), p1.PackageName)
105*ba677afaSXin Li
106*ba677afaSXin Li		for _, pkg := range docSecond.Packages {
107*ba677afaSXin Li			if pkg.PackageSPDXIdentifier == pkgID {
108*ba677afaSXin Li				okSecond = true
109*ba677afaSXin Li				p2 = pkg
110*ba677afaSXin Li				break
111*ba677afaSXin Li			}
112*ba677afaSXin Li		}
113*ba677afaSXin Li		if !okSecond {
114*ba677afaSXin Li			fmt.Printf("  Found in first document, not found in second\n")
115*ba677afaSXin Li			continue
116*ba677afaSXin Li		}
117*ba677afaSXin Li
118*ba677afaSXin Li		// now, run a diff between the two
119*ba677afaSXin Li		pairs, err := licensediff.MakePairs2_2(p1, p2)
120*ba677afaSXin Li		if err != nil {
121*ba677afaSXin Li			fmt.Printf("  Error generating licensediff pairs: %v\n", err)
122*ba677afaSXin Li			continue
123*ba677afaSXin Li		}
124*ba677afaSXin Li
125*ba677afaSXin Li		// take the pairs and turn them into a more structured results set
126*ba677afaSXin Li		resultSet, err := licensediff.MakeResults(pairs)
127*ba677afaSXin Li		if err != nil {
128*ba677afaSXin Li			fmt.Printf("  Error generating licensediff results set: %v\n", err)
129*ba677afaSXin Li			continue
130*ba677afaSXin Li		}
131*ba677afaSXin Li
132*ba677afaSXin Li		// print some information about the results
133*ba677afaSXin Li		fmt.Printf("  Files in first only: %d\n", len(resultSet.InFirstOnly))
134*ba677afaSXin Li		fmt.Printf("  Files in second only: %d\n", len(resultSet.InSecondOnly))
135*ba677afaSXin Li		fmt.Printf("  Files in both with different licenses: %d\n", len(resultSet.InBothChanged))
136*ba677afaSXin Li		fmt.Printf("  Files in both with same licenses: %d\n", len(resultSet.InBothSame))
137*ba677afaSXin Li	}
138*ba677afaSXin Li
139*ba677afaSXin Li	// now report if there are any package IDs in the second set that aren't
140*ba677afaSXin Li	// in the first
141*ba677afaSXin Li	for _, pkgID := range pkgIDsSecond {
142*ba677afaSXin Li		var p2 *v2_2.Package
143*ba677afaSXin Li		var okFirst, okSecond bool
144*ba677afaSXin Li		for _, pkg := range docSecond.Packages {
145*ba677afaSXin Li			if pkg.PackageSPDXIdentifier == pkgID {
146*ba677afaSXin Li				okSecond = true
147*ba677afaSXin Li				p2 = pkg
148*ba677afaSXin Li				break
149*ba677afaSXin Li			}
150*ba677afaSXin Li		}
151*ba677afaSXin Li		if !okSecond {
152*ba677afaSXin Li			fmt.Printf("================================\n")
153*ba677afaSXin Li			fmt.Printf("Package %s has described relationship in second document but ID not found\n", string(pkgID))
154*ba677afaSXin Li			continue
155*ba677afaSXin Li		}
156*ba677afaSXin Li
157*ba677afaSXin Li		for _, pkg := range docFirst.Packages {
158*ba677afaSXin Li			if pkg.PackageSPDXIdentifier == pkgID {
159*ba677afaSXin Li				okFirst = true
160*ba677afaSXin Li				break
161*ba677afaSXin Li			}
162*ba677afaSXin Li		}
163*ba677afaSXin Li		if !okFirst {
164*ba677afaSXin Li			fmt.Printf("================================\n")
165*ba677afaSXin Li			fmt.Printf("Package %s (%s)\n", string(pkgID), p2.PackageName)
166*ba677afaSXin Li			fmt.Printf("  Found in second document, not found in first\n")
167*ba677afaSXin Li		}
168*ba677afaSXin Li	}
169*ba677afaSXin Li}
170