Skip to content

Commit

Permalink
Enable simple flag for regeneration and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
filip-debricked committed Aug 20, 2024
1 parent 2df8b39 commit a4ad6b2
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 20 deletions.
28 changes: 13 additions & 15 deletions internal/cmd/fingerprint/fingerprint.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package fingerprint

import (
"errors"
"fmt"
"path/filepath"
"time"

"github.com/debricked/cli/internal/fingerprint"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -63,7 +63,7 @@ $ debricked scan . --include '**/node_modules/**'`)
cmd.Flags().BoolVar(&shouldFingerprintCompressedContent, FingerprintCompressedContent, false, `Fingerprint the contents of compressed files by unpacking them in memory, Supported files: `+fmt.Sprintf("%v", fingerprint.ZIP_FILE_ENDINGS))
cmd.Flags().StringVar(&outputDir, OutputDirFlag, ".", "The directory to write the output file to")
cmd.Flags().IntVar(&minFingerprintContentLength, MinFingerprintContentLengthFlag, 45, "Set minimum content length (in bytes) for files to fingerprint. Defaults to 45 bytes.")
cmd.Flags().BoolVar(&shouldRegenerateFingerprintFile, RegenerateFingerprintFile, true, `If generated fingerprint file should be overwritten on subequent scans. Defaults to true`)
cmd.Flags().BoolVar(&shouldRegenerateFingerprintFile, RegenerateFingerprintFile, true, `Toggle if generated fingerprint file should be overwritten on subequent scans. Defaults to true`)

viper.MustBindEnv(ExclusionFlag)

Expand All @@ -76,30 +76,28 @@ func RunE(f fingerprint.IFingerprint) func(_ *cobra.Command, args []string) erro
if len(args) > 0 {
path = args[0]
}
var outputFilePath = filepath.Join(outputDir, fingerprint.OutputFileNameFingerprints)
options := fingerprint.DebrickedOptions{
OutputPath: outputFilePath,
Regenerate: shouldRegenerateFingerprintFile,
Path: path,
Exclusions: exclusions,
Inclusions: inclusions,
FingerprintCompressedContent: shouldFingerprintCompressedContent,
MinFingerprintContentLength: minFingerprintContentLength,
}
output, err := f.FingerprintFiles(options)

if err != nil {
if errors.Is(err, &fingerprint.FingerprintFileExistsError{}) {
fmt.Println(
"Fingerprint file exists and command is configured to not overwrite. ",
"To generate new fingerprint file either remove/rename old file or ",
"change flag '--regenerate' to 'true'",
)
return nil
}
return err
}
var outputFilePath string
// TODO: decide if we should only create a date-suffix file if a file without date-suffix already exists.
// Depending on decision, check for existence of debricked.fingerprints.txt here.
if shouldRegenerateFingerprintFile {
outputFilePath = filepath.Join(outputDir, fingerprint.OutputFileNameFingerprints)
} else {
// TODO: decide on if date suffix is what we want or if an incrementing integer should be used.
timestamp := time.Now().Format("2006-01-02_15-04-05") // reference date, do not change the date, only format
ext := filepath.Ext(fingerprint.OutputFileNameFingerprints)
ouputFileName := fmt.Sprintf("%s_%s%s", fingerprint.OutputFileNameFingerprints, timestamp, ext)
outputFilePath = filepath.Join(outputDir, ouputFileName)
}

err = output.ToFile(outputFilePath)
if err != nil {
Expand Down
26 changes: 22 additions & 4 deletions internal/cmd/fingerprint/fingerprint_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fingerprint

import (
"io"
"os"
"testing"

Expand Down Expand Up @@ -44,16 +45,33 @@ func TestNewFingerprintCmd(t *testing.T) {

func TestRunE(t *testing.T) {
defer func() {
os.Remove(fingerprint.OutputFileNameFingerprints) // TODO: make sure it will remove all generated fingerprint files (e.g. with date suffix)
os.Remove(fingerprint.OutputFileNameFingerprints)
}()
fingerprintMock := testdata.NewFingerprintMock()
runE := RunE(fingerprintMock)

err := runE(nil, []string{"."})

assert.NoError(t, err)
// TODO: Run command again, first with regenerate=true (default) to ensure no extra file is generated (check only one exists)
// Run command a third time, without regenerate,
// asserting that a date-stamped debricked fingerprint file is created when regenerate=false
}

func TestRunEFileExistsError(t *testing.T) {
defer func() {
os.Remove(fingerprint.OutputFileNameFingerprints)
}()
fingerprintMock := testdata.NewFingerprintMockFileExistsError()
runE := RunE(fingerprintMock)

rescueStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w

err := runE(nil, []string{"."})

_ = w.Close()
output, _ := io.ReadAll(r)
os.Stdout = rescueStdout

assert.NoError(t, err)
assert.Contains(t, string(output), "change flag '--regenerate' to 'true'")
}
21 changes: 20 additions & 1 deletion internal/fingerprint/fingerprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type DebrickedOptions struct {
Inclusions []string
FingerprintCompressedContent bool
MinFingerprintContentLength int
OutputPath string
Regenerate bool
}

var ZIP_FILE_ENDINGS = []string{".jar", ".nupkg", ".war", ".zip", ".ear", ".whl"}
Expand Down Expand Up @@ -59,6 +61,12 @@ func NewFingerprinter() *Fingerprinter {
}
}

type FingerprintFileExistsError struct{}

func (_ *FingerprintFileExistsError) Error() string {
return "Fingerprint file already exists and command is configured to not overwrite."
}

type FileFingerprint struct {
path string
contentLength int64
Expand All @@ -78,14 +86,25 @@ func (f *Fingerprinter) FingerprintFiles(options DebrickedOptions) (Fingerprints

fingerprints := Fingerprints{}

_, err := os.Open(options.OutputPath)
var fingerprintFileExists = false
if !errors.Is(err, os.ErrNotExist) {
fingerprintFileExists = true
}
fmt.Printf("output path=%s", options.OutputPath)
fmt.Printf("regen=%t, file=%t\n", options.Regenerate, fingerprintFileExists)
if !options.Regenerate && fingerprintFileExists {
return fingerprints, &FingerprintFileExistsError{}
}

f.spinnerManager.Start()
spinnerMessage := "files processed"
spinner := f.spinnerManager.AddSpinner(spinnerMessage)

nbFiles := 0
lastLogNb := 0

err := filepath.Walk(options.Path, func(path string, fileInfo os.FileInfo, err error) error {
err = filepath.Walk(options.Path, func(path string, fileInfo os.FileInfo, err error) error {
if err != nil {
return err
}
Expand Down
19 changes: 19 additions & 0 deletions internal/fingerprint/fingerprint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,25 @@ func TestFingerprintFiles(t *testing.T) {

}

func TestFingerprintFilesAlreadyExists(t *testing.T) {
temp, err := os.CreateTemp("testdata/fingerprinter", "temp-fingerprint-*.txt")
fingerprinter := NewFingerprinter()
_, err = fingerprinter.FingerprintFiles(
DebrickedOptions{
OutputPath: temp.Name(),
Path: "testdata/fingerprinter",
Exclusions: []string{},
Inclusions: []string{},
FingerprintCompressedContent: false,
MinFingerprintContentLength: 0,
Regenerate: false,
},
)
os.Remove(temp.Name())
assert.Error(t, err)
assert.Contains(t, err.Error(), "Fingerprint file already exists")
}

func TestFingerprintFilesBackslash(t *testing.T) {

tempDir, err := os.MkdirTemp("", "slash-test")
Expand Down
6 changes: 6 additions & 0 deletions internal/fingerprint/testdata/fingerprinter_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ func NewFingerprintMock() *FingerprintMock {
}
}

func NewFingerprintMockFileExistsError() *FingerprintMock {
return &FingerprintMock{
error: &fingerprint.FingerprintFileExistsError{},
}
}

func (f *FingerprintMock) FingerprintFiles(
options fingerprint.DebrickedOptions,
) (fingerprint.Fingerprints, error) {
Expand Down

0 comments on commit a4ad6b2

Please sign in to comment.