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