diff options
author | Steve Winslow <swinslow@gmail.com> | 2018-10-24 17:46:56 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-24 17:46:56 -0400 |
commit | 941fa33ea499c1f9092818a264a38600efe1acce (patch) | |
tree | 27f7bbf471ef74dbde5a01003862d80aa198bcc9 /examples | |
parent | d4c19259c711d59d26040295112d6d2fd618faa1 (diff) | |
download | spdx-tools-941fa33ea499c1f9092818a264a38600efe1acce.tar.gz |
Added examples (#29)
Closes #27
Signed-off-by: Steve Winslow <swinslow@gmail.com>
Diffstat (limited to 'examples')
-rw-r--r-- | examples/1-load/example_load.go | 92 | ||||
-rw-r--r-- | examples/2-load-save/example_load_save.go | 68 | ||||
-rw-r--r-- | examples/3-build/example_build.go | 117 | ||||
-rw-r--r-- | examples/4-search/example_search.go | 148 | ||||
-rw-r--r-- | examples/5-report/example_report.go | 77 | ||||
-rw-r--r-- | examples/README.md | 44 |
6 files changed, 546 insertions, 0 deletions
diff --git a/examples/1-load/example_load.go b/examples/1-load/example_load.go new file mode 100644 index 0000000..994f7f7 --- /dev/null +++ b/examples/1-load/example_load.go @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +// Example for: *tvloader*, *spdx* + +// This example demonstrates loading an SPDX tag-value file from disk into +// memory, and printing some of its contents to standard output. + +package main + +import ( + "fmt" + "os" + + "github.com/swinslow/spdx-go/v0/tvloader" +) + +func main() { + + // check that we've received the right number of arguments + args := os.Args + if len(args) != 2 { + fmt.Printf("Usage: %v <spdx-file-in>\n", args[0]) + fmt.Printf(" Load SPDX 2.1 tag-value file <spdx-file-in>, and\n") + fmt.Printf(" print a portion of its contents.\n") + return + } + + // open the SPDX file + filename := args[1] + r, err := os.Open(filename) + if err != nil { + fmt.Printf("Error while opening %v for reading: %v", filename, err) + return + } + defer r.Close() + + // try to load the SPDX file's contents as a tag-value file, version 2.1 + doc, err := tvloader.Load2_1(r) + if err != nil { + fmt.Printf("Error while parsing %v: %v", filename, err) + return + } + + // if we got here, the file is now loaded into memory. + fmt.Printf("Successfully loaded %s\n\n", filename) + + // we can now take a look at its contents via the various data + // structures representing the SPDX document's sections. + + // print the struct containing the SPDX file's Creation Info section data + fmt.Printf("==============\n") + fmt.Printf("Creation info:\n") + fmt.Printf("==============\n") + fmt.Printf("%#v\n\n", doc.CreationInfo) + + // check whether the SPDX file has at least one package + if doc.Packages == nil || len(doc.Packages) < 1 { + fmt.Printf("No packages found in SPDX document\n") + return + } + + // it does, so we'll choose the first one + pkg := doc.Packages[0] + + // check whether the package had its files analyzed + if !pkg.FilesAnalyzed { + fmt.Printf("First Package (%s) had FilesAnalyzed: false\n", pkg.PackageName) + return + } + + // also check whether the package has any files present + if pkg.Files == nil || len(pkg.Files) < 1 { + fmt.Printf("No Files found in first Package (%s)\n", pkg.PackageName) + return + } + + // if we got here, there's at least one file + // print the filename and license info for the first 50 + fmt.Printf("============================\n") + fmt.Printf("Files info (up to first 50):\n") + fmt.Printf("============================\n") + i := 1 + for _, f := range pkg.Files { + fmt.Printf("File %d: %s\n", i, f.FileName) + fmt.Printf(" License from file: %v\n", f.LicenseInfoInFile) + fmt.Printf(" License concluded: %v\n", f.LicenseConcluded) + i++ + if i > 50 { + break + } + } +} diff --git a/examples/2-load-save/example_load_save.go b/examples/2-load-save/example_load_save.go new file mode 100644 index 0000000..4a5cfc6 --- /dev/null +++ b/examples/2-load-save/example_load_save.go @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +// Example for: *tvloader*, *tvsaver* + +// This example demonstrates loading an SPDX tag-value file from disk into memory, +// and re-saving it to a different file on disk. + +package main + +import ( + "fmt" + "os" + + "github.com/swinslow/spdx-go/v0/tvloader" + "github.com/swinslow/spdx-go/v0/tvsaver" +) + +func main() { + + // check that we've received the right number of arguments + args := os.Args + if len(args) != 3 { + fmt.Printf("Usage: %v <spdx-file-in> <spdx-file-out>\n", args[0]) + fmt.Printf(" Load SPDX 2.1 tag-value file <spdx-file-in>, and\n") + fmt.Printf(" save it out to <spdx-file-out>.\n") + return + } + + // open the SPDX file + fileIn := args[1] + r, err := os.Open(fileIn) + if err != nil { + fmt.Printf("Error while opening %v for reading: %v", fileIn, err) + return + } + defer r.Close() + + // try to load the SPDX file's contents as a tag-value file, version 2.1 + doc, err := tvloader.Load2_1(r) + if err != nil { + fmt.Printf("Error while parsing %v: %v", fileIn, err) + return + } + + // if we got here, the file is now loaded into memory. + fmt.Printf("Successfully loaded %s\n", fileIn) + + // we can now save it back to disk, using tvsaver. + + // create a new file for writing + fileOut := args[2] + w, err := os.Create(fileOut) + if err != nil { + fmt.Printf("Error while opening %v for writing: %v", fileOut, err) + return + } + defer w.Close() + + // try to save the document to disk as an SPDX tag-value file, version 2.1 + err = tvsaver.Save2_1(doc, w) + if err != nil { + fmt.Printf("Error while saving %v: %v", fileOut, err) + return + } + + // it worked + fmt.Printf("Successfully saved %s\n", fileOut) +} diff --git a/examples/3-build/example_build.go b/examples/3-build/example_build.go new file mode 100644 index 0000000..5ddafdd --- /dev/null +++ b/examples/3-build/example_build.go @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +// Example for: *builder*, *tvsaver* + +// This example demonstrates building an 'empty' SPDX document in memory that +// corresponds to a given directory's contents, including all files with their +// hashes and the package's verification code, and saving the document to disk. + +package main + +import ( + "fmt" + "os" + + "github.com/swinslow/spdx-go/v0/builder" + "github.com/swinslow/spdx-go/v0/tvsaver" +) + +func main() { + + // check that we've received the right number of arguments + args := os.Args + if len(args) != 4 { + fmt.Printf("Usage: %v <package-name> <package-root-dir> <spdx-file-out>\n", args[0]) + fmt.Printf(" Build a SPDX 2.1 document with one package called <package-name>;\n") + fmt.Printf(" create files with hashes corresponding to the files in <package-root-dir>;\n") + fmt.Printf(" and save it out as a tag-value file to <spdx-file-out>.\n") + return + } + + // get the command-line arguments + packageName := args[1] + packageRootDir := args[2] + fileOut := args[3] + + // to use the SPDX builder package, the first step is to define a + // builder.Config2_1 struct. this config data can be reused, in case you + // are building SPDX documents for several directories in sequence. + config := &builder.Config2_1{ + + // NamespacePrefix is a prefix that will be used to populate the + // mandatory DocumentNamespace field in the Creation Info section. + // Because it needs to be unique, the value that will be filled in + // for the document will have the package name and verification code + // appended to this prefix. + NamespacePrefix: "https://example.com/whatever/testdata-", + + // CreatorType will be used for the first part of the Creator field + // in the Creation Info section. Per the SPDX spec, it can be + // "Person", "Organization" or "Tool". + CreatorType: "Person", + + // Creator will be used for the second part of the Creator field in + // the Creation Info section. + Creator: "Jane Doe", + + // note that builder will also add the following, in addition to the + // Creator defined above: + // Creator: Tool: github.com/swinslow/spdx-go/v0/builder + + // Finally, you can define one or more paths that should be ignored + // when walking through the directory. This is intended to omit files + // that are located within the package's directory, but which should + // be omitted from the SPDX document. + PathsIgnored: []string{ + + // ignore all files in the .git/ directory at the package root + "/.git/", + + // ignore all files in all __pycache__/ directories, anywhere + // within the package directory tree + "**/__pycache__/", + + // ignore the file with this specific path relative to the + // package root + "/.ignorefile", + + // or ignore all files with this filename, anywhere within the + // package directory tree + "**/.DS_Store", + }, + } + + // now, when we actually ask builder to walk through a directory and + // build an SPDX document, we need to give it three things: + // - what to name the package; and + // - where the directory is located on disk; and + // - the config object we just defined. + doc, err := builder.Build2_1(packageName, packageRootDir, config) + if err != nil { + fmt.Printf("Error while building document: %v\n", err) + return + } + + // if we got here, the document has been created. + // all license info is marked as NOASSERTION, but file hashes and + // the package verification code have been filled in appropriately. + fmt.Printf("Successfully created document for package %s\n", packageName) + + // we can now save it to disk, using tvsaver. + + // create a new file for writing + w, err := os.Create(fileOut) + if err != nil { + fmt.Printf("Error while opening %v for writing: %v\n", fileOut, err) + return + } + defer w.Close() + + err = tvsaver.Save2_1(doc, w) + if err != nil { + fmt.Printf("Error while saving %v: %v", fileOut, err) + return + } + + fmt.Printf("Successfully saved %v\n", fileOut) +} diff --git a/examples/4-search/example_search.go b/examples/4-search/example_search.go new file mode 100644 index 0000000..0abbf7e --- /dev/null +++ b/examples/4-search/example_search.go @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +// Example for: *idsearcher*, *tvsaver* + +// This example demonstrates building an SPDX document for a directory's +// contents (implicitly using *builder*); searching through that directory for +// [SPDX short-form IDs](https://spdx.org/ids/); filling those IDs into the +// document's Package and File license fields; and saving the resulting document +// to disk. + +package main + +import ( + "fmt" + "os" + + "github.com/swinslow/spdx-go/v0/idsearcher" + + "github.com/swinslow/spdx-go/v0/tvsaver" +) + +func main() { + + // check that we've received the right number of arguments + args := os.Args + if len(args) != 4 { + fmt.Printf("Usage: %v <package-name> <package-root-dir> <spdx-file-out>\n", args[0]) + fmt.Printf(" Build a SPDX 2.1 document with one package called <package-name>;\n") + fmt.Printf(" create files with hashes corresponding to the files in <package-root-dir>;\n") + fmt.Printf(" search for SPDX short-form IDs, and use them to fill in license data\n") + fmt.Printf(" where possible; and save it out as a tag-value file to <spdx-file-out>.\n") + return + } + + // get the command-line arguments + packageName := args[1] + packageRootDir := args[2] + fileOut := args[3] + + // to use the SPDX idsearcher package, the first step is to define a + // idsearcher.Config2_1 struct. this config data can be reused, in case you + // are building SPDX documents for several directories in sequence. + config := &idsearcher.Config{ + + // NamespacePrefix is a prefix that will be used to populate the + // mandatory DocumentNamespace field in the Creation Info section. + // Because it needs to be unique, the value that will be filled in + // for the document will have the package name and verification code + // appended to this prefix. + NamespacePrefix: "https://example.com/whatever/testdata-", + + // CreatorType and Creator, from builder.Config2_1, are not needed for + // idsearcher.Config. Because it is automated and doesn't assume + // further review, the following two Creator fields are filled in: + // Creator: Tool: github.com/swinslow/spdx-go/v0/builder + // Creator: Tool: github.com/swinslow/spdx-go/v0/idsearcher + + // You can define one or more paths that should be ignored + // when walking through the directory. This is intended to omit files + // that are located within the package's directory, but which should + // be omitted from the SPDX document. + // This is directly passed through to builder, and uses the same + // format as shown in examples/3-build/example_build.go. + BuilderPathsIgnored: []string{ + + // ignore all files in the .git/ directory at the package root + "/.git/", + + // ignore all files in all __pycache__/ directories, anywhere + // within the package directory tree + "**/__pycache__/", + + // ignore the file with this specific path relative to the + // package root + "/.ignorefile", + + // or ignore all files with this filename, anywhere within the + // package directory tree + "**/.DS_Store", + }, + + // Finally, SearcherPathsIgnored lists certain paths that should not be + // searched by idsearcher, even if those paths have Files present (and + // had files filled in by builder). This is useful, for instance, if + // your project has some directories or files with + // "SPDX-License-Identifier:" tags, but for one reason or another you + // want to exclude those files' tags from being picked up by the + // searcher. + // SearcherPathsIgnored uses the same format as BuilderPathsIgnored. + SearcherPathsIgnored: []string{ + + // Example for the Linux kernel: ignore the documentation file + // which explains how to use SPDX short-form IDs (and therefore + // has a bunch of "SPDX-License-Identifier:" tags that we wouldn't + // want to pick up). + "/Documentation/process/license-rules.rst", + + // Similar example for the Linux kernel: ignore all files in the + // /LICENSES/ directory. + "/LICENSES/", + }, + } + + // now, when we actually ask idsearcher to walk through a directory and + // build an SPDX document, we need to give it three things: + // - what to name the package; and + // - where the directory is located on disk; and + // - the config object we just defined. + // these are the same arguments needed for builder, and in fact they get + // passed through to builder (with the relevant data from the config + // object extracted behind the scenes). + doc, err := idsearcher.BuildIDsDocument(packageName, packageRootDir, config) + if err != nil { + fmt.Printf("Error while building document: %v\n", err) + return + } + + // if we got here, the document has been created. + // all file hashes and the package verification code have been filled in + // appropriately by builder. + // And, all files with "SPDX-License-Identifier:" tags have had their + // licenses extracted into LicenseInfoInFile and LicenseConcluded for + // each file by idsearcher. The PackageLicenseInfoFromFiles field will + // also be filled in with all license identifiers. + fmt.Printf("Successfully created document and searched for IDs for package %s\n", packageName) + + // NOTE that BuildIDsDocument does NOT do any validation of the license + // identifiers, to confirm that they are e.g. on the SPDX License List + // or in other appropriate format (e.g., LicenseRef-...) + + // we can now save it to disk, using tvsaver. + + // create a new file for writing + w, err := os.Create(fileOut) + if err != nil { + fmt.Printf("Error while opening %v for writing: %v\n", fileOut, err) + return + } + defer w.Close() + + err = tvsaver.Save2_1(doc, w) + if err != nil { + fmt.Printf("Error while saving %v: %v", fileOut, err) + return + } + + fmt.Printf("Successfully saved %v\n", fileOut) +} diff --git a/examples/5-report/example_report.go b/examples/5-report/example_report.go new file mode 100644 index 0000000..5506a68 --- /dev/null +++ b/examples/5-report/example_report.go @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +// Example for: *reporter*, *tvloader* + +// This example demonstrates loading an SPDX tag-value file from disk into memory, +// generating a basic report listing counts of the concluded licenses for its +// files, and printing the report to standard output. + +package main + +import ( + "fmt" + "os" + + "github.com/swinslow/spdx-go/v0/reporter" + "github.com/swinslow/spdx-go/v0/tvloader" +) + +func main() { + + // check that we've received the right number of arguments + args := os.Args + if len(args) != 2 { + fmt.Printf("Usage: %v <spdx-file-in>\n", args[0]) + fmt.Printf(" Load SPDX 2.1 tag-value file <spdx-file-in>, and\n") + fmt.Printf(" generate and print a report of its concluded licenses.\n") + return + } + + // open the SPDX file + filename := args[1] + r, err := os.Open(filename) + if err != nil { + fmt.Printf("Error while opening %v for reading: %v", filename, err) + return + } + defer r.Close() + + // try to load the SPDX file's contents as a tag-value file, version 2.1 + doc, err := tvloader.Load2_1(r) + if err != nil { + fmt.Printf("Error while parsing %v: %v", filename, err) + return + } + + // if we got here, the file is now loaded into memory. + fmt.Printf("Successfully loaded %s\n\n", filename) + + // check whether the SPDX file has at least one package + if doc.Packages == nil || len(doc.Packages) < 1 { + fmt.Printf("No packages found in SPDX document\n") + return + } + + // it does, so we'll choose the first one + pkg := doc.Packages[0] + + // check whether the package had its files analyzed + if !pkg.FilesAnalyzed { + fmt.Printf("First Package (%s) had FilesAnalyzed: false\n", pkg.PackageName) + return + } + + // also check whether the package has any files present + if pkg.Files == nil || len(pkg.Files) < 1 { + fmt.Printf("No Files found in first Package (%s)\n", pkg.PackageName) + return + } + + // if we got here, there's at least one file + // generate and print a report of the Package's Files' LicenseConcluded + // values, sorted by # of occurrences + err = reporter.Generate(pkg, os.Stdout) + if err != nil { + fmt.Printf("Error while generating report: %v\n", err) + } +} diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..64e41f2 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,44 @@ +SPDX-License-Identifier: CC-BY-4.0 + +# spdx-go Examples + +The `examples/` directory contains examples for how to use the various spdx-go sub-packages. + +## 1-load/ + +*tvloader*, *spdx* + +This example demonstrates loading an SPDX tag-value file from disk into memory, +and printing some of its contents to standard output. + +## 2-load-save/ + +*tvloader*, *tvsaver* + +This example demonstrates loading an SPDX tag-value file from disk into memory, +and re-saving it to a different file on disk. + +## 3-build/ + +*builder*, *tvsaver* + +This example demonstrates building an 'empty' SPDX document in memory that +corresponds to a given directory's contents, including all files with their +hashes and the package's verification code, and saving the document to disk. + +## 4-search/ + +*idsearcher*, *tvsaver* + +This example demonstrates building an SPDX document for a directory's contents +(implicitly using *builder*); searching through that directory for [SPDX +short-form IDs](https://spdx.org/ids/); filling those IDs into the document's +Package and File license fields; and saving the resulting document to disk. + +## 5-report/ + +*reporter*, *tvloader* + +This example demonstrates loading an SPDX tag-value file from disk into memory, +generating a basic report listing counts of the concluded licenses for its +files, and printing the report to standard output. |