Skip to content

Commit

Permalink
spdx.buildIDString function
Browse files Browse the repository at this point in the history
This new functions generates a valid SPDX ID string, optionally
it can take strings as seeds to generate a more intuitive ID for
packages and files.

Signed-off-by: Adolfo García Veytia (Puerco) <adolfo.garcia@uservers.net>
  • Loading branch information
puerco authored and justaugustus committed Nov 21, 2021
1 parent 2452215 commit 9e70e0a
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 19 deletions.
8 changes: 1 addition & 7 deletions pkg/spdx/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"html/template"
"log"
"os"
"regexp"
"time"

"github.com/google/uuid"
Expand Down Expand Up @@ -93,12 +92,7 @@ func (d *Document) AddPackage(pkg *Package) error {
}

if pkg.ID == "" {
// If we so not have an ID but have a name generate it fro there
reg := regexp.MustCompile("[^a-zA-Z0-9-]+")
id := reg.ReplaceAllString(pkg.Name, "")
if id != "" {
pkg.ID = "SPDXRef-Package-" + id
}
pkg.BuildID(pkg.Name)
}
if pkg.ID == "" {
return errors.New("package id is needed to add a new package")
Expand Down
5 changes: 5 additions & 0 deletions pkg/spdx/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,8 @@ func (f *File) ReadSourceFile(path string) error {
f.ID = "SPDXRef-File-" + f.Checksum["SHA256"][0:15]
return nil
}

// BuildID sets the file ID, optionally from a series of strings
func (f *File) BuildID(seeds ...string) {
f.ID = "SPDXRef-File" + "-" + buildIDString(seeds...)
}
15 changes: 7 additions & 8 deletions pkg/spdx/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"fmt"
"html/template"
"path/filepath"
"regexp"
"sort"
"strings"
"sync"
Expand Down Expand Up @@ -157,23 +156,23 @@ func (p *Package) AddFile(file *File) error {
if _, err := h.Write([]byte(p.Name + ":" + file.Name)); err != nil {
return errors.Wrap(err, "getting sha1 of filename")
}
file.ID = "SPDXRef-File-" + fmt.Sprintf("%x", h.Sum(nil))
file.BuildID(fmt.Sprintf("%x", h.Sum(nil)))
}
p.Files[file.ID] = file
return nil
}

// BuildID sets the package ID, optionally from a series of strings
func (p *Package) BuildID(seeds ...string) {
p.ID = "SPDXRef-Package" + "-" + buildIDString(seeds...)
}

// preProcessSubPackage performs a basic check on a package
// to ensure it can be added as a subpackage, trying to infer
// missing data when possible
func (p *Package) preProcessSubPackage(pkg *Package) error {
if pkg.ID == "" {
// If we so not have an ID but have a name generate it fro there
reg := regexp.MustCompile(validNameCharsRe)
id := reg.ReplaceAllString(pkg.Name, "")
if id != "" {
pkg.ID = "SPDXRef-Package-" + id
}
p.BuildID(pkg.Name)
}
if pkg.ID == "" {
return errors.New("package name is needed to add a new package")
Expand Down
34 changes: 30 additions & 4 deletions pkg/spdx/spdx.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const (
spdxLicenseData = spdxTempDir + "/licenses"
spdxLicenseDlCache = spdxTempDir + "/downloadCache"
gitIgnoreFile = ".gitignore"
validNameCharsRe = `[^a-zA-Z0-9-]+`
validIDCharsRe = `[^a-zA-Z0-9-.]+` // https://spdx.github.io/spdx-spec/3-package-information/#32-package-spdx-identifier

// Consts of some SPDX expressions
NONE = "NONE"
Expand Down Expand Up @@ -95,6 +95,34 @@ type TarballOptions struct {
ExtractDir string // Directory where the docker tar archive will be extracted
}

// buildIDString takes a list of seed strings and builds a
// valid SPDX ID string from them. If none is supplied, an
// ID using an UUID will be returned
func buildIDString(seeds ...string) string {
validSeeds := []string{}
for _, s := range seeds {
reg := regexp.MustCompile(validIDCharsRe)
s = reg.ReplaceAllString(s, "")
if s != "" {
validSeeds = append(validSeeds, s)
}
}

// If we did not get any seeds, use an UUID
if len(validSeeds) == 0 {
validSeeds = append(validSeeds, uuid.New().String())
}

id := ""
for _, s := range validSeeds {
if id != "" {
id += "-"
}
id += s
}
return id
}

// PackageFromDirectory indexes all files in a directory and builds a
// SPDX package describing its contents
func (spdx *SPDX) PackageFromDirectory(dirPath string) (pkg *Package, err error) {
Expand Down Expand Up @@ -137,9 +165,7 @@ func (spdx *SPDX) PackageFromDirectory(dirPath string) (pkg *Package, err error)
pkg = NewPackage()
pkg.FilesAnalyzed = true
pkg.Name = filepath.Base(dirPath)
// If the package file will result in an empty ID, generate one
reg := regexp.MustCompile(validNameCharsRe)
if reg.ReplaceAllString(pkg.Name, "") == "" {
if pkg.Name == "" {
pkg.Name = uuid.NewString()
}
pkg.LicenseConcluded = licenseTag
Expand Down
24 changes: 24 additions & 0 deletions pkg/spdx/spdx_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,30 @@ import (
"sigs.k8s.io/release-utils/util"
)

func TestBuildIDString(t *testing.T) {
cases := []struct {
seeds []string
expected string
}{
{[]string{"1234"}, "1234"},
{[]string{"abc"}, "abc"},
{[]string{"ABC"}, "ABC"},
{[]string{"ABC", "123"}, "ABC-123"},
{[]string{"Hello:bye", "123"}, "Hellobye-123"},
{[]string{"Hello:bye", "123", "&^%&$"}, "Hellobye-123"},
}
for _, tc := range cases {
require.Equal(t, tc.expected, buildIDString(tc.seeds...))
}

// If we do not pass any seeds, func should return an UUID
// which is 36 chars long
require.Len(t, buildIDString(), 36)

// Same thing for only invalid chars
require.Len(t, buildIDString("&^$&^%"), 36)
}

func TestUnitExtractTarballTmp(t *testing.T) {
tar := writeTestTarball(t)
require.NotNil(t, tar)
Expand Down

0 comments on commit 9e70e0a

Please sign in to comment.