xref: /aosp_15_r20/external/spdx-tools/examples/3-build/example_build.go (revision ba677afa8f67bb56cbc794f4d0e378e0da058e16)
1// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2
3// Example for: *builder*, *tvsaver*
4
5// This example demonstrates building an 'empty' SPDX document in memory that
6// corresponds to a given directory's contents, including all files with their
7// hashes and the package's verification code, and saving the document to disk.
8// Run project: go run example_build.go project2 ../../testdata/project2 test.spdx
9
10package main
11
12import (
13	"fmt"
14	"os"
15
16	"github.com/spdx/tools-golang/builder"
17	"github.com/spdx/tools-golang/tvsaver"
18)
19
20func main() {
21
22	// check that we've received the right number of arguments
23	args := os.Args
24	if len(args) != 4 {
25		fmt.Printf("Usage: %v <package-name> <package-root-dir> <spdx-file-out>\n", args[0])
26		fmt.Printf("  Build a SPDX 2.2 document with one package called <package-name>;\n")
27		fmt.Printf("  create files with hashes corresponding to the files in <package-root-dir>;\n")
28		fmt.Printf("  and save it out as a tag-value file to <spdx-file-out>.\n")
29		return
30	}
31
32	// get the command-line arguments
33	packageName := args[1]
34	packageRootDir := args[2]
35	fileOut := args[3]
36
37	// to use the SPDX builder package, the first step is to define a
38	// builder.Config2_2 struct. this config data can be reused, in case you
39	// are building SPDX documents for several directories in sequence.
40	config := &builder.Config2_2{
41
42		// NamespacePrefix is a prefix that will be used to populate the
43		// mandatory DocumentNamespace field in the Creation Info section.
44		// Because it needs to be unique, the value that will be filled in
45		// for the document will have the package name and verification code
46		// appended to this prefix.
47		NamespacePrefix: "https://example.com/whatever/testdata-",
48
49		// CreatorType will be used for the first part of the Creator field
50		// in the Creation Info section. Per the SPDX spec, it can be
51		// "Person", "Organization" or "Tool".
52		CreatorType: "Person",
53
54		// Creator will be used for the second part of the Creator field in
55		// the Creation Info section.
56		Creator: "Jane Doe",
57
58		// note that builder will also add the following, in addition to the
59		// Creator defined above:
60		// Creator: Tool: github.com/spdx/tools-golang/builder
61
62		// Finally, you can define one or more paths that should be ignored
63		// when walking through the directory. This is intended to omit files
64		// that are located within the package's directory, but which should
65		// be omitted from the SPDX document.
66		PathsIgnored: []string{
67
68			// ignore all files in the .git/ directory at the package root
69			"/.git/",
70
71			// ignore all files in all __pycache__/ directories, anywhere
72			// within the package directory tree
73			"**/__pycache__/",
74
75			// ignore the file with this specific path relative to the
76			// package root
77			"/.ignorefile",
78
79			// or ignore all files with this filename, anywhere within the
80			// package directory tree
81			"**/.DS_Store",
82		},
83	}
84
85	// now, when we actually ask builder to walk through a directory and
86	// build an SPDX document, we need to give it three things:
87	//   - what to name the package; and
88	//   - where the directory is located on disk; and
89	//   - the config object we just defined.
90	doc, err := builder.Build2_2(packageName, packageRootDir, config)
91	if err != nil {
92		fmt.Printf("Error while building document: %v\n", err)
93		return
94	}
95
96	// if we got here, the document has been created.
97	// all license info is marked as NOASSERTION, but file hashes and
98	// the package verification code have been filled in appropriately.
99	fmt.Printf("Successfully created document for package %s\n", packageName)
100
101	// we can now save it to disk, using tvsaver.
102
103	// create a new file for writing
104	w, err := os.Create(fileOut)
105	if err != nil {
106		fmt.Printf("Error while opening %v for writing: %v\n", fileOut, err)
107		return
108	}
109	defer w.Close()
110
111	err = tvsaver.Save2_2(doc, w)
112	if err != nil {
113		fmt.Printf("Error while saving %v: %v", fileOut, err)
114		return
115	}
116
117	fmt.Printf("Successfully saved %v\n", fileOut)
118}
119