Skip to content

Commit

Permalink
Add option to generate a new fingerprint file or not. (#248)
Browse files Browse the repository at this point in the history
* add option to generate a new fingerprint file or not.

* Enable simple flag for regeneration and add tests

* Add regenerate pass through from scan to fingerprint

---------

Co-authored-by: Filip Hedén <[email protected]>
Anton Duppils and filip-debricked authored Aug 26, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 04e5703 commit 707a677
Showing 6 changed files with 83 additions and 3 deletions.
20 changes: 18 additions & 2 deletions internal/cmd/fingerprint/fingerprint.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fingerprint

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

@@ -14,13 +15,15 @@ var inclusions []string
var shouldFingerprintCompressedContent bool
var outputDir string
var minFingerprintContentLength int
var shouldRegenerateFingerprintFile bool

const (
ExclusionFlag = "exclusion"
InclusionFlag = "inclusion"
FingerprintCompressedContent = "fingerprint-compressed-content"
OutputDirFlag = "output-dir"
MinFingerprintContentLengthFlag = "min-fingerprint-content-length"
RegenerateFingerprintFile = "regenerate"
)

func NewFingerprintCmd(fingerprinter fingerprint.IFingerprint) *cobra.Command {
@@ -60,6 +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, `Toggle if generated fingerprint file should be overwritten on subequent scans. Defaults to true`)

viper.MustBindEnv(ExclusionFlag)

@@ -72,19 +76,31 @@ 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 a new fingerprint file either remove/rename old file or ",
"change flag '--regenerate' to 'true'",
)

return nil
}

return err
}
outputFilePath := filepath.Join(outputDir, fingerprint.OutputFileNameFingerprints)

err = output.ToFile(outputFilePath)
if err != nil {
return err
21 changes: 21 additions & 0 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"

@@ -52,5 +53,25 @@ func TestRunE(t *testing.T) {
err := runE(nil, []string{"."})

assert.NoError(t, err)
}

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'")
}
19 changes: 18 additions & 1 deletion internal/fingerprint/fingerprint.go
Original file line number Diff line number Diff line change
@@ -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"}
@@ -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
@@ -78,14 +86,23 @@ 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
}
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
}
19 changes: 19 additions & 0 deletions internal/fingerprint/fingerprint_test.go
Original file line number Diff line number Diff line change
@@ -183,6 +183,25 @@ func TestFingerprintFiles(t *testing.T) {

}

func TestFingerprintFilesAlreadyExists(t *testing.T) {
temp, _ := 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")
6 changes: 6 additions & 0 deletions internal/fingerprint/testdata/fingerprinter_mock.go
Original file line number Diff line number Diff line change
@@ -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) {
1 change: 1 addition & 0 deletions internal/scan/scanner.go
Original file line number Diff line number Diff line change
@@ -172,6 +172,7 @@ func (dScanner *DebrickedScanner) scanFingerprint(options DebrickedOptions) erro
Inclusions: append(options.Inclusions, fingerprint.DefaultInclusionsFingerprint()...),
MinFingerprintContentLength: options.MinFingerprintContentLength,
FingerprintCompressedContent: false,
Regenerate: options.Regenerate > 0,
},
)
if err != nil {

0 comments on commit 707a677

Please sign in to comment.