Skip to content

Commit

Permalink
Clean up (#12)
Browse files Browse the repository at this point in the history
Signed-off-by: naveensrinivasan <172697+naveensrinivasan@users.noreply.github.com>
  • Loading branch information
naveensrinivasan authored Jul 19, 2024
1 parent ed21d95 commit 2d1acd8
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 11 deletions.
File renamed without changes.
34 changes: 34 additions & 0 deletions pkg/file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package pkg

import (
"testing"
)

// TestSanitizeFilename tests the SanitizeFilename function.
func TestSanitizeFilename(t *testing.T) {
tests := []struct {
input string
expected string
}{
{input: "file/name", expected: "file_name"},
{input: "file\\name", expected: "file_name"},
{input: "file:name", expected: "file_name"},
{input: "file*name", expected: "file_name"},
{input: "file?name", expected: "file_name"},
{input: "file\"name", expected: "file_name"},
{input: "file<name", expected: "file_name"},
{input: "file>name", expected: "file_name"},
{input: "file|name", expected: "file_name"},
{input: "file/name\\name:name*name?name\"name<name>name|name", expected: "file_name_name_name_name_name_name_name_name_name"},
{input: "filename", expected: "filename"},
}

for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
result := SanitizeFilename(test.input)
if result != test.expected {
t.Errorf("SanitizeFilename(%q) = %q; want %q", test.input, result, test.expected)
}
})
}
}
23 changes: 18 additions & 5 deletions pkg/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import (

var ErrNodeAlreadyExists = errors.New("node with name already exists")

type Direction string

const (
ParentDirection Direction = "parent"
ChildDirection Direction = "child"
)

// Generic Node structure with metadata as generic type
type Node[T any] struct {
Metadata T `json:"metadata"`
Expand Down Expand Up @@ -118,6 +125,9 @@ func (n *Node[T]) SetDependency(storage Storage[T], neighbor *Node[T]) error {
if n.Id == neighbor.Id {
return fmt.Errorf("cannot add self as dependency")
}
if storage == nil {
return fmt.Errorf("storage cannot be nil")
}

n.Child.Add(neighbor.Id)
neighbor.Parent.Add(n.Id)
Expand All @@ -131,10 +141,13 @@ func (n *Node[T]) SetDependency(storage Storage[T], neighbor *Node[T]) error {
return nil
}

func (n *Node[T]) queryBitmap(storage Storage[T], direction string) (*roaring.Bitmap, error) {
func (n *Node[T]) queryBitmap(storage Storage[T], direction Direction) (*roaring.Bitmap, error) {
if n == nil {
return nil, fmt.Errorf("cannot query bitmap of nil node")
}
if storage == nil {
return nil, fmt.Errorf("storage cannot be nil")
}

result := roaring.New()
visited := make(map[uint32]bool)
Expand All @@ -151,9 +164,9 @@ func (n *Node[T]) queryBitmap(storage Storage[T], direction string) (*roaring.Bi

var bitmap *roaring.Bitmap
switch direction {
case "child":
case ChildDirection:
bitmap = curNode.Child
case "parent":
case ParentDirection:
bitmap = curNode.Parent
default:
return nil, fmt.Errorf("invalid direction during query: %s", direction)
Expand All @@ -173,9 +186,9 @@ func (n *Node[T]) queryBitmap(storage Storage[T], direction string) (*roaring.Bi
}

func (n *Node[T]) QueryDependents(storage Storage[T]) (*roaring.Bitmap, error) {
return n.queryBitmap(storage, "parent")
return n.queryBitmap(storage, ParentDirection)
}

func (n *Node[T]) QueryDependencies(storage Storage[T]) (*roaring.Bitmap, error) {
return n.queryBitmap(storage, "child")
return n.queryBitmap(storage, ChildDirection)
}
20 changes: 15 additions & 5 deletions pkg/ingest.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package pkg
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"

Expand All @@ -12,21 +11,21 @@ import (
"github.com/protobom/protobom/pkg/sbom"
)

// IngestSBOM ingests a SBOM file or directory into the storage backend.
func IngestSBOM(sbomPath string, storage Storage[any]) error {
info, err := os.Stat(sbomPath)
if err != nil {
return fmt.Errorf("error accessing path %s: %w", sbomPath, err)
}

if info.IsDir() {
entries, err := ioutil.ReadDir(sbomPath)
entries, err := os.ReadDir(sbomPath)
if err != nil {
return fmt.Errorf("failed to read directory %s: %w", sbomPath, err)
}
for _, entry := range entries {
entryPath := filepath.Join(sbomPath, entry.Name())
err := IngestSBOM(entryPath, storage)
if err != nil {
if err := IngestSBOM(entryPath, storage); err != nil {
return fmt.Errorf("failed to ingest SBOM from path %s: %w", entryPath, err)
}
}
Expand All @@ -37,8 +36,18 @@ func IngestSBOM(sbomPath string, storage Storage[any]) error {
return nil
}

// processSBOMFile processes a SBOM file and adds it to the storage backend.
func processSBOMFile(filePath string, storage Storage[any]) error {
if filePath == "" {
return fmt.Errorf("file path is empty")
}

_, err := os.Stat(filePath)
if err != nil {
return fmt.Errorf("failed to stat file %s: %w", filePath, err)
}
sbomReader := reader.New()

document, err := sbomReader.ParseFile(filePath)
if err != nil {
return fmt.Errorf("failed to parse SBOM file %s: %w", filePath, err)
Expand All @@ -49,6 +58,7 @@ func processSBOMFile(filePath string, storage Storage[any]) error {
graphNode, err := AddNode(storage, node.Type.String(), any(node), roaring.New(), roaring.New(), string(node.Purl()))
if err != nil {
if errors.Is(err, ErrNodeAlreadyExists) {
// TODO: Add a logger
fmt.Println("Skipping...")
continue
}
Expand Down Expand Up @@ -88,4 +98,4 @@ func addDependency(document *sbom.Document, storage Storage[any], nameToNodeID m
}
}
return nil
}
}
1 change: 1 addition & 0 deletions pkg/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/RoaringBitmap/roaring"
)

// ParseAndExecute parses and executes a script using the given storage backend.
func ParseAndExecute[T any](script string, storage Storage[T]) (*roaring.Bitmap, error) {
var stack []*roaring.Bitmap
var operators []string
Expand Down
6 changes: 5 additions & 1 deletion pkg/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/RoaringBitmap/roaring"
)

// Storage is the interface that wraps the methods for a storage backend.
type Storage[T any] interface {
NameToID(name string) (uint32, error)
IDToName(id uint32) (string, error)
Expand All @@ -19,10 +20,13 @@ type Storage[T any] interface {
}

var (
// storageInstance is the singleton instance of the storage interface.
storageInstance Storage[any]
once sync.Once
// once is a sync.Once that ensures that the storage instance is only initialized once.
once sync.Once
)

// GetStorageInstance returns a singleton instance of the storage interface.
func GetStorageInstance(addr string) Storage[any] {
once.Do(func() {
storageInstance = NewRedisStorage[any](addr)
Expand Down

0 comments on commit 2d1acd8

Please sign in to comment.